Previous Next Table of Contents

2. Using SML/NJ

2.1 Starting and Stopping the Interpreter

To start the interpreter, at the Unix command line, type sml. To exit the interpreter, type ^D (control + D) (section 1.2 in Ullman). If you are using a Windows or (lamentably) a DOS machine, type ^Z instead.

Note: There is an executable file in /home/jeffm/bin/ called sml. You must either run this file to start SML, or copy this file to a place in your path before you can use it.

2.2 Creating and Using Source Files

SML/NJ is a command-line interpreter. It is not an integrated development environment. Therefore, you must create and edit source code files using your favorite text editor. Save your source files with the extension .sml. The interpreter doesn't care what the extension is, but SML/NJ files customarily end with this extension.

Ideally, you will have more than one window open on your desktop, be it in X-Windows, Microsoft Windows 95/98/NT, or Be. In another window, start the SML interpreter, but make sure you are first in the same directory where the source file is saved. This makes your life much easier. When the SML prompt appears, type use "filename.sml";. The file will then be loaded, and lots of information will be displayed. If the last line is val it = () : unit, then it loaded successfully. If one or more error messages were displayed, then the file did not load and you need to fix the errors in your source file.

2.3 Using ML

Read chapter 1 and 2 of the Ullman book, try as many of the examples as possible. It is helpful to sit at a computer running ML as you read the book, and try things out as you read about them.

SML/NJ is available on the Unix computers, but feel free to get it for your own computer. I'm not sure if the SML/NJ dialect will be necessary (CAML and OCAML are notable alternatives), but you should stick with it just in case.

The ML interpreter is a read-eval-print loop. The user enters expressions at the SML command prompt, and the interpreter evaluates the expression and displays the result. (Chapter 1)

An expression is terminated by a semicolon.

2.4 Variables

A variable is declared and defined using the ``val'' keyword.

val x = 10;

This creates a new entry in the environment. Once bound, a variable's value can't be changed. A new binding using the same symbolic name can be created, and it overrides the existing one (but it does not replace it).

Be sure to read and understand example 2.24 on page 32 (which deals with rebinding values in an environment).

2.5 Tuples

A list in ML is a linked list, and it is similar to a list in Lisp or Scheme. The difference is that a list in ML may only contain objects of the same type. A tuple is similar to a record structure in C or Pascal, and the elements can be of any type.

Parentheses are used to create tuples, and the ``#'' accessor can be used to access fields in a tuple:

> val t = (4, 5.0, "six");
val t = (4, 5.0, "six") : int * real * string

> #1(t)
val it = 4 : int

(Although by using functions there is a more effective method of accessing tuple fields.)

A tuple can be used to pass arguments to a function, to bind values to a variable, and to return values from a function. A tuple can contain any type of object in any position, including a list or another tuple.

2.6 Lists

A list is created by using square brackets, and commas separate elements in a list. Elements in a list must all be of the same type. The ``hd'' and ``tl'' operators are used to access elements of a list.

> val m = [1, 2, 3];
val m = [1, 2, 3] : int list

> hd(m);
1 : int

> tl(m);
[2, 3] : int list

(Although, as with tuples, functions provide a better way to access list elements.)

``::'' is the list constructor, ``@'' is the list concatenator.

> 1::2::3::nil;
[1, 2, 3] : int list

> 1::[2, 3];
[1, 2, 3] : int list

> [1, 2] @ [3, 4];
[1, 2, 3, 4] : int list

ML's types are all built upon the basic types and tuples and lists. Be sure to read and understand section 2.4.6 and example 2.38 in Ullman.

Previous Next Table of Contents