p is to write #2 p.
This style is not idiomatic or readable. The proper way to handle
this is by pattern matching, so
fun first (x, _) = x fun second (_, y) = yis preferred, and not
fun bogus_first p = #1 p fun bogus_second p = #2 p(For reasons I don't want to discuss, but will answer in class if asked, these versions don't even type-check.) If your pair or tuple is not an argument to a function, use
val to do the pattern matching:
val (x, y) = lookup_pair mumbleBut usually you can include matching in ordinary
fun
matching.
Points will be deducted on homework for using #1,
#2, and their friends.
option, which lets you
handle it.
The definition of option is
datatype 'a option = NONE | SOME of 'aand it is already defined when you start the interactive system. You need not and should not define it yourself.
Some examples
- datatype chesspiece = K | Q | R | N | B | P - type square = chesspiece option - val empty : square = NONE - val lower_left : square = SOME R - fun play piece = SOME piece : square; > val play = fn : chesspiece -> chesspiece option - SOME true; > val it = SOME true : bool option - SOME 37; > val it = SOME 37 : int option - SOME "fish" = SOME "fowl"; > val it = false : bool - SOME "fish" = NONE; > val it = false : bool - "fish" = NONE; ! Toplevel input: ! "fish" = NONE; ! ^^^^ ! Type clash: expression of type ! 'a option ! cannot be made to have type ! string
The option type is covered in Ullman on pages 111-113,
208, etc.
Array structure
in Chapter 7, he
doesn't cover the immutable Vector structure except for a
couple of pages deep in Chapter 9.
Like an array, a vector
offers constant-time access to an array of elements, but a vector is not
mutable.
Because of its immutability, Vector is often preferred.
It is especially flexible when initialized with
Vector.tabulate.
Here's the signature:
signature VECTOR =
sig
eqtype 'a vector
val maxLen : int
val fromList : 'a list -> 'a vector
val tabulate : int * (int -> 'a) -> 'a vector
val length : 'a vector -> int
val sub : 'a vector * int -> 'a
val extract : 'a vector * int * int option -> 'a vector
val concat : 'a vector list -> 'a vector
val app : ('a -> unit) -> 'a vector -> unit
val foldl : ('a * 'b -> 'b) -> 'b -> 'a vector -> 'b
val foldr : ('a * 'b -> 'b) -> 'b -> 'a vector -> 'b
val appi : (int * 'a -> unit) -> 'a vector * int * int option -> unit
val foldli : (int * 'a * 'b -> 'b)
-> 'b -> 'a vector * int * int option -> 'b
val foldri : (int * 'a * 'b -> 'b)
-> 'b -> 'a vector * int * int option -> 'b
end
It makes me deeply unhappy to have to warn you that the
signature for Vector was changed in 2004, and that
although the MLton compiler has tracked this change, and Standard ML
of New Jersey has tracked parts of the change, Moscow ML has not
tracked the change at all. For simplicity, you are best off sticking
with Moscow ML and using MLton with the -basis 1997
option, but you need to know that these are not consistent with the
current documentation on the web.