A Functional Programming Language: ML
A Programming Language is:
- a language for a virtual compuation environment
- a very formal language
- precise syntax (structure)
- Which symbols can be used, and how can they be composed
- precise semantics (meaning)
- What do the symbols mean
ML:
- a functional programming language (i.e., based on math. functions)
- designed by Robin Milner
ML Expressions -- Composition of values and operators, ended with a
semicolon
1+2*3;
val it = 7 : int
ML evaluates the expression given, and prints the result
- the result has a name - it
- the result has a value - 7
- the result has a type - int
Type is a very important and fundamental concept
- defines a set of values that can be used
- expressions must have type consistency
- so, integers, reals, booleans, and strings are the fundamental types
in ML
ML has Constants of five types:
- Integers -- a string of digits (0-9), optionally preceded
by a tilde (~) to indicate negative
- Do we really need to say what an integer is? Yes.
- Reals -- string of digits (possibly preceded by ~), followed
by at least one of
- a decimal point and one or more digits
- the letter E, followed by an integer
- Booleans -- true or false
- Characters -- Ascii characters, e.g., #"A"
- Strings -- a sequence of characters enclosed with double-quotes (")
- \ is a special character, and means that the next character
(or more) indicate something special
- \n is the newline character, basically just like hitting
the Return key
- \t is the tab character -- like hitting the Tab key
- \\ is the backslash -- since one \ is special, just
type \\ to really mean backslash
- \" is the double-quote -- a plain double-quote would
mean the end of the string, to have a double-quote actually be in the string,
you use \"
- \### is a way to specify a character by its ASCII number
- \^A for any letter A is a way to specify a control character
- \ as the last character on the line means the string continues
on the following line
Arithmetic operators: +,-,*,/,div,mod,~
Question: What order of evaluation?
Answer: operators have precedence relations
- negation (unary minus) is evaluated first (highest precendence)
- multiplication operators are next
- addition operators are last
- parentheses, of course, override these rules (technically, they have
highest precedence)
Question: When are spaces needed?
Answer: when ML can't figure it out itself
String operators:
- ^ is concatenation; that is, it makes one string out of two by slapping
them together, end to end
- "" is an empty string, and is allowed
Comparison (Relational) Operators: =, <, >, <=, >=,
<>
- These can compare two values of the same type: integer, real, or string
- The result is a value of type Boolean (true or false)
- They have lower precedence than any arithmetic operators (i.e., evaluate
after)
Logical Operators: andalso, orelse, not
- They can only operate on Boolean values, and result in Boolean values
- Even lower precedence than Comparison operators, and orelse is
lower than andalso
- orelse is an inclusive or, as opposed to an exclusive
or
- Truthtables of each (done in class)
If-then-else Operator
- An operator? Yes, it takes operands and evaluates to a result
- The form is if expr1 then expr2 else expr3
- expr1 must result in a Boolean value
- expr2 and expr3 must result in values of the same type
- the result of the if-then-else operator is the value of expr2 if expr1
is true, otherwise it is the value of expr3; the type of the result is
the type of expr2 and expr3
some examples found here
Type consistency
- ML is a strongly typed language
- Every operator (and function) has a specific type signature,
and this cannot be violated.
- For example, the operator ^ (which concatenates two strings)
has a type signature of string*string->string
- reads as "takes a string and another string, and results in a
string".
- order is important for the *
- What about +? We used it with both integers and reals. What
is its type signature?
- it has two: int*int->int and real*real->real
- but not int*real or real*int!
- we say that + is an overloaded operator, because it
has more than one signature
- Resulting types do not have to be the same as the argument types. The
type signatures of the overloaded relational operator > are:
- int*int->bool
- real*real->bool
- string*string->bool
- The type signature of the if-then-else operator is bool*t*t->t where
t is some type.
Type conversion (coercion)
- Values can be converted between types
- Think of the coercion as a function taking one argument of a type,
and returning a value of another type.
- Easiest: integer to real: real(3) is 3.0
- What about real to integer: depends on how you want it:
- floor, ceil (ceiling), trunc (truncate)
- character to integer? integer to character?
- string to integer? real to string?
Identifiers
- The val statement associates an identifier with a value (which
can be computed from an expression)
- The value still has a specific type, even when referenced through the
identifier
- val pi = 3.14156; means that the identifier pi refers
to the real value 3.14156
- The identifier can be used in an expression, or in general any place
a value of that type can be used
- Type consistency is still maintained
- Identifiers are not
declared ahead of time to hold specific types; they are simply assigned
typed values.
Some more examples here