15-212: Principles of Programming

Language and Programming Environment

The programming environment we will be using for the course will
be the Standard ML of New Jersey system (known as SML/NJ). This guide
provides instructions for how to set up your Andrew account to use
SML/NJ, and a brief introduction to using the SML/NJ system. This is
not intended as a guide to programming in Standard ML; for that
purpose you are referred to the course textbook and the on-line notes.

Standard ML is a safe, modular, strict, functional, polymorphic
programming language with compile-time type checking and type
inference, garbage collection, exception handling, immutable data
types and updatable references, abstract data types, and parametric
modules. It has efficient implementations and a formal definition with
a proof of soundness. For explanations of these terms see "What is Standard ML?"

Installation and Use of SML/NJ

How to run SML/NJ at CMU

To use SML/NJ from Linux machines in an Andrew
cluster, type sml at a command prompt.
That should be equivalent to typing:
/usr/local/bin/sml
(To exit, type C-d
("Control D") at the SML prompt.)

Personal Copies of SML/NJ

To use SML/NJ on your own machine please visit the
SML/NJ homepage.NB: The version installed on Andrew is 110.69. The
TAs will use this version to grade assignments. You may wish to
install it on your own machine. It is available
here.

A convenient way to run SML/NJ is via the SML mode for Gnu Emacs.
See this page for additional details.

Starting SML/NJ

With your .emacs file set up for SML, you may enter SML
mode either by loading any file with a .sml or .sig
extension, or by typing M-x sml-mode. The SML mode provides
indentation and other facility that may be helpful in editing SML
source code.

Once in the SML mode, you can start SML/NJ by typing M-x sml, or by
selecting SML/Process/Start default ML compiler from the menu. This
will start SML/NJ running in the background. You can then bring up an SML/NJ
window by typing C-c C-s, or by selecting SML/Process/switch to ML
buffer from the menu. On some machines SML/NJ may be slow to load; if the
window comes up empty, be patient.

If you prefer not to run SML/NJ through Emacs, you may also run it
from the Unix prompt at path
/afs/andrew/course/15/212sp/bin/sml.

Interacting with SML/NJ

Once SML/NJ has started, it prints the current version number and
then prompts for user input. The prompt is a single dash. At the
prompt you may type an SML top-level declaration or an SML expression.
When you enter a declaration, SML/NJ evaluates the declaration, prints
its result value and type, and prompts for more input. For example:

- val a = 2 + 3;
val a = 5 : int
-

This declaration sets a equal to the value of 2 + 3, that is, 5.
The semicolon at the end of the input line tells the SML parser that its input
is complete. By leaving off the semicolon you may enter multi-line declarations
or expressions. Each line after the first is prompted by an equals. For
example, we may declare a two-line increment function by:

- fun inc x =
= x + 1;
val inc = fn : int -> int
-

In each of the above examples, the identifier being declared (a or
inc) is available in code that follows. When you enter an expression
at the user prompt, SML/NJ treats that expression as a declaration for the
identifier it. For example:

- inc a;
val it = 6 : int
- it * 3;
val it = 18 : int
-

Using files

The interactive loop, as the above is called, is a convenient way to evaluate
small expressions and declarations, but it is not practical for larger pieces of
code. For larger pieces of code we want to load them directly into SML/NJ from
a file. This is done by running the use command. SML/NJ will then
process the file as if it had been entered into the interactive loop (except
that no semicolon is needed at the end of the file). For example, suppose the
file myprog.sml contained the code:

The final binding to it happens because SML/NJ views use
"myprog.sml" as an expression and, as discussed above, treats that expression
as a declaration for the identifier it. The value of this expression is
(), which is pronounced ``unit.''

Idiosyncrasies

When SML/NJ prints a data structure, it prints that data structure only to a
certain depth. Beneath that depth it prints a # instead. This is
generally a good thing, since data structures can be very large (and even
cyclic). However, the default depth to which SML/NJ prints data structures is
5, which is usually not enough. You can adjust the depth to which it prints
data structures by entering, for example,

- Control.Print.printDepth := 10;

to set the depth to 10. SML/NJ also abbreviates lists and strings over a certain
length. You can set the length at which this happens by setting
Control.Print.printLength and
Control.Print.stringDepth, in a manner analogous to the
above.

When the argument to use is not a full path name, SML/NJ looks for source
files in the working directory. You can set SML/NJ's working directory by
entering, for example,

- OS.FileSys.chDir "newdir";

to change the working directory to ``newdir.'' Windows users should note that
the SML syntax for strings doubles backslashes. You can also find out what the
working directory is with the command: