Most of what we do below will be described via keyboard shortcuts. You can do most of it as well with the menus within Emacs, if you like - but you'll be much faster and more effective in the end if you learn the keyboard techniques.
The settings for emacs are placed in a file called ".emacs" that is contained in your home directory. Have you modified your .emacs before? To find out, change to your home directory and issue the following command:
ls -la .emacs
Look at the right hand column. If you see a symbolic link like
.emacs -> /usr/local/skel/.emacs
then you have no modifications to make. Your .emacs file is a symbolic link to the system standard .emacs, which Mike Tie has recently updated to contain settings for color and ML indentation. Skip the remaining steps in this part and skip to Part 1 of this lab.
On the other hand, if you do not see a symbolic link, then you have modified your .emacs file in the past. Open up your .emacs file (in emacs or any other editor if choice), and add the following lines to the end if they don't already appear in there somewhere:
(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/sml-mode")
(load "sml-mode-startup")
1. Start up emacs by typing
emacs &
at the command prompt. The "&" means start it as a background job, so that you still have access to the command line if you want it.
2. In emacs, most commands are proceeded by either ctrl-x or alt-x. To start working on a program, type ctrl-x, ctrl-f (the f means "find"), and give emacs a directory and a filename. For example, I might type "~/cs217/sml/prog1.sml". Emacs will open up this file if it exists, or will present you a new blank file.
Type in a very simple ML program just to try it out. For example, enter in the code
val x = 3;
Now save this program by typing ctrl-x, ctrl-s (the s means "save").
4. Open up a second window inside emacs by typing ctrl-x, 2 (the 2 indicates two windows). To switch between windows, you can either use the mouse or enter the command ctrl-x, o (the o means "other"). Switch to the bottom window, enter alt-x, and at the command prompt type the word shell. This opens up a command line prompt within emacs. Change to the directory in which you stored your SML program. For example, if I stored my SML program in the directory ~/cs217/sml, I would type
cd ~/cs217/sml
5. Start up SML by typing
sml
at the prompt. This may take a little time to start up.
6. Run your program in SML. To do this, type
use "prog1.sml";
(or substitute here whatever you named your program).
7. Change your program in some way. For example, change it to read
val x = 8;
Save your program again by typing ctrl-x, ctrl-s.
9. Re-run your program. To avoid having to type the "use" command again, use alt-p to move backwards through your command history. alt-n will move forwards.
10. To exit SML, enter ctrl-d. To exit from the command prompt, type exit. You should see a message that says "process shell finished". Finally, to exit emacs, type ctrl-x, ctrl-c.
Last word of encouragement: emacs is many, many times more powerful than gedit, nedit, pico, and the other editors floating around the system. As a result, it's more difficult to learn. If you stick with it and learn the keyboard shortcuts, however, you'll be able to edit your code considerably faster than when using the other tools (vi religion wars aside). It took me about a month of regular coding to feel comfortable in emacs. I never went back!
hd [5,2,1,7,8];
hd([5,2,1,7,8]);
tl [5,2,1,7,8];
tl([5,2,1,7,8]);
What do hd and tl do? Why are the parentheses optional?
The response that you get from SML indicates the answer in a variable called it, as well as a type (either int, or int list). Why is the type different for the functions hd and tl?
2. Write a sequence of hd and tl that will pick the string "pear" out of the following expression.
["apple", "orange", "pear", "grapefruit"]
3. Execute the following statements. One of them gives an error. Why? What are the corresponding names for the operators :: and @ in Scheme? (Both of these operators in SML are read out loud the same way in SML as you would pronounce the corresponding operators in Scheme).
(* This is a comment, by the way! *)
1::[2,3];
[1,5]::[2,3];
[1,5]@[2,3];
4. When are lists equal? Experiment and find out. For example, what happens when you enter the following?
[1,2]=[1,2,3];
4. Execute the following code. What do length and rev do?
length ["plato","socrates","aristotle"];
rev ["plato","socrates","aristotle"];
fn x => x + 1;
What does ML return? fn and the => operator return a function without a name. In this case, you have defined a function to take one argument and add 1 to it. What is this equivalent to in Scheme?
2. A function without a name is useless, as it is immediately garbage collected. Try this instead:
val addOne =
fn x => x + 1;
(Use the "tab" key to indent your code. Emacs will indent all your code correctly, automatically.)
Then try:
addOne 5;
The val statement created a binding to a function, called addOne, which refers to the function you just created.
3. The above can be entered via shorthand as
fun addOne x =
x + 1;
Try it! Remember, this is just shorthand for the slightly longer code above.
4. Try this for size:
val anotherAddOne = addOne;
anotherAddOne(5);
At the pointer level, what is happening here? Draw a picture on this paper indicating what is happening.
5. Try the following code. What does let do?
let
val x = 10
in
x * x
end;
fun mystery(L) =
if L = nil then
L
else
mystery(tl(L)) @ [hd(L)];
2. Write a recursive function, keepFirstN, that returns a list of the first n elements in a list. You may assume that there are at least n elements.
Example:
keepFirstN(3,["a","b","c","d","e","f","g","h","i"]);
["a","b","c"]
fun mystery([]) = []
| mystery(start::rest) =
mystery(rest) @ [start:int];
2. Here are a few more examples of pattern matching. Try them and figure out what's going on. What does the underscore do?
fun fact(1) = 1
| fact(n) = n*fact(n-1);
fun last([]) = ~1
| last(first::nil) = first
| last(_::rest) = last(rest);
3. Rewrite keepFirstN using pattern matching.
let fun loop(count) =
(
print("Count = ");
print(Int.toString(count));
print("\n");
if count < 10 then
loop(count+1)
else
count
)
in
loop(0)
end;
SMLofNJ.Internals.GC.messages(false);