GIML: A Glossary

! dereference
'a type parameter
''a ditto with equality
# record reference
: .. of type
:: cons
@ append
_ anonymous parameter
and mutual recursion
as another name for..
andalso boolean and
datatype data definition
fun function definition
hd head of a list
if .. then .. else ..
it last result
length length of a list
null test for empty list
o function composition
op infix to prefix
orelse boolean operator
rev reverse a list
size length of a string
substring extract part of a string
tl tail of a list
type name a type
val define a label
!
Never use this - it dereferences pointers. Its use brings shame on all who dabble with it (and an F grade if it shows up in assessments).
- val nasty = ref 1;
val nasty = ref 1 : int ref
- !nasty;
val it = 1 : int
- nasty := 2;
val it = () : unit
- !nasty;
val it = 2 : int
'a
A "type variable" used to indicate that any type can be used here (also 'b 'c ...)
- length;
val it = fn : 'a list -> int
The input type for length is 'a because length works for lists of any type (e.g. lists of integers or strings or functions)
- datatype 'a Leafless = lltip | llnode of 'a * 'a Leafless * 'a Leafless;

- datatype ('a,'b) Tree = tip of 'a
                        | node of 'b*(('a,'b)Tree)*(('a,'b)Tree);
Leafless is a tree with data at the nodes only. Tree is a tree with 'a s at the tips and 'b s at the nodes.
''a
Used to indicate a type which supports equality. Ordinary types like int and string support equality (you can test to see if one int equals another). Some types (such as functions) do not permit such tests.
- fun member x nil = false
= |   member x (h::t) = (x=h) orelse member x t;
val member = fn : ''a -> ''a list -> bool
We can apply member only where the type permits equality...
- member 1 [2,3];
val it = false : bool
The above is OK as int supports equality
- member tl [tl,rev];
std_in:11.1-11.18 Error: operator and operand don't agree (equality type required)
  operator domain: ''Z
  operand:         'Y list -> 'Y list
  in expression:
    member tl
The above fails type checking as tl and rev are functions, lists of functions may be used where the type is simple 'a...
- length [tl,rev];
val it = 2 : int
- 
#
This is used to access fields of a record (not covered in GIML)
- val emp1 = {name="Andrew",address="Cloud-cuckooland",salary=1000000};
- #salary emp1;
val it = 1000000 : int
Tuples are "special" records with field named 1, 2, 3 ...
#4(2,3,5,7,11,13);
val it = 7 : int
:
May be used to specify type.
- fun add(x : int, y: int) = x + y;
val add = fn : int * int -> int
::
Cons. This constructs a list - it takes an item and a list and returns a list.
- 1::[2,3];
val it = [1,2,3] : int list

- 1::2::3::nil;
val it = [1,2,3] : int list

@
The append operator. This is used to join two lists together.
Example of use:
- [1,2,3] @ [3,4,5];
val it = [1,2,3,3,4,5] : int list
The definition of @ is as follows...
fun    nil @ x = x
|   (h::t) @ x = h::(t@x);
_
The underscore can be used as a "place-holder" in patterns on the left hand side of equations - it should never appear on the right. It may be used to indicate the presence of a parameter whose value is not used. This "anonymous" label may be repeated on the left hand side - in which case it may stand for different values in each position.
For example in the definition of hd we match the pattern h::t but we do not care about the value of t
fun hd(h::_)=h;
instead of
fun hd(h::t)=h;
and
This may be used to define mutually recursive functions and datatypes.
datatype Expr       = Sum of Term list
and      Term       = Product of Factor list
and      Factor     = Variable of string | Value of int | Bracket of Expr;
(* Not a good example as it is easier to have just one type here ...
datatype Expr = Sum of Expr list | 
                Prod of Expr list |
                Var of string|
                Val of int;
*)
                
fun foo(h::t) = h+bar t
|   foo nil   = 0
and bar(h::t) = (~h)+foo t
|   bar nil   = 0;
andalso
A boolean "and". Note that it is lazy in that the second value is not evaluated unless it is required. (also see orelse)
- (42 div 7 = 6) andalso (42 mod 7 = 0);
val it = true : bool
- (42 div 7 = 7) andalso (hd nil = 0);
val it = false : bool
Note that no run time error occurs even though hd nil would raise an exception.
as
This can be used to allow more than one way of referring to a structure. This is a perfectly safe and sensible thing to do given referential transparency.
fun triangle nil = nil
|   triangle (l as h::t) = l::triangle t;

triangle ["Oh", "Sir", "Jasper"];
val it = [["Oh","Sir","Jasper"],["Sir","Jasper"],["Jasper"]] : string list list
datatype
Used to introduce new datatypes. Alternate "tags" or constructors are given components using the of key word.
- datatype Shape = Square of int | Rectangle of int * int;
datatype  Shape
  con Rectangle : int * int -> Shape
  con Square : int -> Shape
fun
This key word is used to define a function.
hd
Returns the head of the list - that is the first element of a list.
- hd ["one", "two", "three"];
val it = "one" : string
The functions hd and tl are very basic functions, they do not show up in ML programs so often as they might because pattern matching often makes their use unnecessary. A typical recursive function in ML might be defined as follows using pattern matching:
fun sum nil   = 0
|   sum(h::t) = h + sum t;
Without pattern matching we would use hd, tl and null.
fun sum x = if null x then 0 else (hd x) + sum(tl x);
if
The if B then X else Y structure returns a value, in the same way that the (B) ? X : Y structure does in c.
In this example count x l returns the number of times that value x occurs in list l.
fun count x nil = 0
|   count x (h::t) = if x=h then 1+count x t else count x t;
or even
fun count x nil = 0
|   count x (h::t) = (if x=h then 1 else 0) + count x t;
it
This "variable" holds the result of the last calculation. It can be handy to use when investigating - but it has no place in a "finished" program.
length
Returns the number of items in a list:
length [2,3,4];
val it = 3 : int
The definition of length is as follows
fun length nil   = 0
|   length(h::t) = 1 + length t;
null
Returns true if the input is an empty list; false otherwise.
- null ["one", "two", "three"];
val it = false : bool
o
Composes two functions. The result is a function. For example
- (implode o rev o explode) "Bolton";
val it = "notloB" : string
op
A handy thing to turn infix operators into prefix functions
- (op +)(2,3);
val it = 5 : int
- fold (op @) [[1,2],[3,4]] nil;
val it = [1,2,3,4] : int list
orelse
Same kind of thing as andalso
rev
Reverses a list
- rev ["Andrew", "was", "here"];
val it = ["here","was","Andrew"] : string list
size
returns the size of a string
- size "five";
val it = 4 : int
substring
The call substring(s, i, n) returns n character from string s at position i. The first character is at position 0.
- substring("delicatessen",4,3);
val it = "cat" : string
tl
Returns the tail of a list: that is everything except the first element
- tl ["one", "two", "three"];
val it = ["two","three"] : string list
Raises the exception Tl if the input list is empty.
type
Allows an alias for a type
type employee = string * string * int;
val
Used to make bindings
- val pi = 3.14159;