pis 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
valto do the pattern matching:
val (x, y) = lookup_pair mumbleBut usually you can include matching in ordinary
Points will be deducted on homework for using
#2, and their friends.
option, which lets you handle it. The definition of
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.
- 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
option type is covered in Ullman on pages 111-113,
Arraystructure in Chapter 7, he doesn't cover the immutable
Vectorstructure 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,
Vectoris 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 endIt makes me deeply unhappy to have to warn you that the signature for
Vectorwas 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 1997option, but you need to know that these are not consistent with the current documentation on the web.