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 contains 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.
Open up a Linux shell inside emacs by typing alt-x, then type the phrase run-sml at the M-x prompt at the
bottom of the screen. Hit enter at the prompt "ML command: sml". (Note: if nothing happens when you type
alt-x, the alt key may not be configured right on your computer. That's
ok - you can simulate hitting alt-x by first hitting the Esc key,
letting go, and then hitting the x).
In the bottom half of your emacs window, you should see the
following:
Standard ML of New Jersey,
Version 110.0.7, September 28, 2000 [CM; autoload
enabled]
-
Type in a very simple ML program just to try it out. At the prompt, enter in the code
val x = 3;
SML should return the following:
val x = 3 : int
7. Change your program in some way. Use alt-p to move backwards through your command history (alt-n will move forwards), and change it to read
val x = 8;
Hit enter.
8. To exit SML, enter ctrl-d. You should see a message that says "process sml 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!
val numbers = [6,4,9,2];
val fruits = ["apple","orange","pineapple"];
What "type" do the brackets define?
(By the
way - if garbage collection messages looking something like
GC #0.0.0.0.1.12: (0 ms)
start bothering you, you can enter
SMLofNJ.Internals.GC.messages(false);
to make them go away.)
2. Enter in the following:
hd ["apple","orange","pineapple"];
tl ["apple","orange","pineapple"];
What do the functions hd and tl do?
The response that you get from SML indicates the answer in a variable called it, as well as a type (either string, or string list). Why is the type different for the functions hd and tl?
3. Write a sequence of hd and tl that will pick the string "pear" out of the following expression.
["apple", "orange", "pear", "grapefruit"]
[[["apple"], ["orange"], ["pear"], ["grapefruit"]]]
4. Execute the following statements. The last four produce errors. Why?
(* This is a comment, by the way! *)
1::[2,3];
"apple"::["pear","orange"];
[1,5]@[2,3];
["apple","grapefruit"]@["pear","orange"];
[2,"apple"];
2::["apple","orange"];
"apple"::[5,7];
5. When are lists equal? Experiment and find out. For example, what happens when you enter the following?
[1,2]=[1,2,3];
6. Execute the following code. What do length and rev do?
length ["plato","socrates","aristotle"];
rev ["plato","socrates","aristotle"];
4. 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 "prog1.sml". Emacs will open up this file if it exists, or
will present you a new blank file.
5. Start typing in your code. Use any of the above examples that you wish. When finished, save your program by typing ctrl-x, ctrl-s (the s means "save").
6. Open a second emacs window from the command prompt. Follow the instructions in Part 1 to start up SML within emacs.use "prog1.sml";
(or substitute here whatever you named your program).fn x => x + 1;
What does ML return? fn and the => operator return a function without a name, also known as an anonymous function. In this case, you have defined a function to take one argument and add 1 to it.
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 pointer 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.
let
val x = 10
in
x * x
end;
x;
What does let do? Why do you get an error when you try to see the value of x after the "let block" has ended?
fun mystery(L) =
if L = nil then
L
else
mystery(tl(L)) @ [hd(L)];
Note that I've used parentheses around the function arguments. This
is optional (in the cases we have seen so far).
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];
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;