C:\>sml Standard ML of New Jersey, Version 110.0.7, September 28, 2000 [CM&CMB] -
The directory from which you start SML is the working directory. When compiling files for problem sets, the working directory needs to be the directory in which the .sml and .cm files for the project reside. The other way to start SML/NJ is in a subshell of Emacs. To do this, when in sml-mode type M-x sml -- this starts the compiler. To switch to the SML/NJ interactive loop type C-c C-s.
The prompt in the interactive loop is -. If you start entering an expression and go to the next line, SML/NJ shows the = sign as the prompt. This means SML is waiting to evaluate the expression until you have finished writing the whole expression. SML knows to evaluate an expression when it sees a semi-colon. Consider the following:
- String.map Char.toUpper = "The quick brown fox jumps over the lazy dog."; val it = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG." : string -
To exit the SML interactive loop, you simply need to send the end-of-file character. On Windows, the end-of-file character is CTRL-Z. On Unix, this is CTRL-D. Since C-z minimizes Emacs, to close an SML subshell you only need to terminate the process first by entering (C-c C-d) in the interactive SML session and then close the buffer (C-x k).
In fact, you'll find that = and <> are special functions not defined in any module of the basis library. These functions only work on some values where determining equality is decisive and inarguable. Real values in SML are based on the IEEE floating point specification, which includes values such as NaN. As computers only have finite storage, it is impossible to always represent every number. Indeed cancellation error can occur, consider "1.0 + 0.000000000001". This evaluates to "1.0". The best way to determine equality is using <= and >= constraining the value to some delta range. Of course, if you want to, Real.== and Real.!= are available for equality tests.
Int.toString Real.round Int.fromString Real.fromInt Real.toString Char.ord Real.fromString Char.chr Real.floor Char.toString Real.ceil Char.fromString Real.trunc String.str
Several of these functions are included in the top-level, including ord, chr, and str. You can look up the exact semantics of each function in the basis library documentation.
general.sml:15.3-15.19 Error: operator and operand don't agree [literal] operator domain: int * int operand: int * real in expression: 40 + 2.0
Let's start from the beginning:
Here is another common error message:
general.sml:15.26 Error: syntax error: inserting IN
Clearly, this is a syntax error. It is suggesting that inserting the keyword in will fix the syntax error. Undoubtedly, you will encounter an indecipherable error message. Fortunately, there is a list of error messages and what they mean.
datatype 'a option = NONE | SOME of 'a
Thus you will note that values in SML are more flexible than those of Java. A good programmer always knows to check for null values when programming in Java or C++. The option type has the advantage that the SML type system forces you to check for NONE values.
GC #8.64.65.66.69.364: (210 ms) 5 4 3 2 1 0 time
The top line is an example of a garbage collection message. Listed below it is the generations. Garbage collection messages only appear when a collection occurs in generations one and above. The numbers listed are the number of garbage collections that have occurred. For instance, in the example above, there have been 8 collections in the 5th generation. Collecting generation one and above are called major collections. Collecting for generation zero is called a minor collection. More important to you is the time listed on the right. In this case, it took 210 milliseconds to complete the garbage collection.
Another common question about garbage collection messages is just how to turn them off. SML/NJ provides for turning off the messages by evaluating the following:
SMLofNJ.Internals.GC.messages false
Passing false to the function turns the messages off. Passing true to this function turns the messages on.
When the system gives the result of an evaluation, it may abbreviate
with the character ``#'' part of the representation of a data structure.
For instance:
- datatype bintree = emp | nod of bintree * int * bintree; datatype bintree = emp | nod of bintree * int * bintree - nod(nod(nod(emp,2,emp),3,emp),1,nod(nod(emp,4,emp),5,emp)); val it = nod (nod (nod #,3,emp),1,nod (nod #,5,emp)) : bintree
In order to avoid this, you can use the "print switches" OF SML, which are:
Compiler.Control.Print.printDepth
(for data structures)
Compiler.Control.Print.printLength
(for lists)
Compiler.Control.Print.stringDepth
(for strings)
You should set these at the prompt:
- Compiler.Control.Print.printDepth := 1000; val it = () : unit - nod(nod(nod(emp,2,emp),3,emp),1,nod(nod(emp,4,emp),5,emp)); val it = nod (nod (nod (emp,2,emp),3,emp),1,nod (nod (emp,4,emp), 5,emp)) : bintree