On Scheme

Thoughts on Scheme and teaching Scheme

Archive for March 11th, 2006

Explaining Let in Terms of Lambda

Posted by Peter on March 11, 2006

Most explanations of let simply explain it as creating temporary symbols which can be assigned values, and that these symbols can only be reached within the body of the let. This is a perfectly valid and informative way of describing how let functions, but I decided to explain it in a different fashion, by appealing to programming constructs already understood by the student. (I assume that the student has already mastered the basics of the lambda statement, realizing that it can be returned from functions, passed to functions, as well as called immediately.)

To motivate the learning process I ask the student how they would go about printing user input, acquired from (read) twice. At first the student may think this is impossible, as if they call read again they will be prompting the user for input again, which is not what they want. So then I ask them if they can write a function taking one argument that prints its argument twice. This is easy enough to do, and once they have this function than printing the user input twice is no problem. Now, to make life more difficult I ask if they can accomplish the same thing in a single function. The brightest students may make the conceptual leap and see that they can do this with lambda, but after demonstrating it even those don’t make the conceptual leap seem to get it. So the program we are writing may look like this:

(defun printtwice ()
  ((lambda (val)
      (display val)
      (display val))
    (read)))

To make things sink in we then cover more examples using this same technique, which also has the benefit of reinforcing how lambda can be used. After the students seem to get it I then introduce let as a kind of shorthand for this construction. (now that I think of it writing let as a macro in terms of this construction may be a good exercise for macros.) I then rewrite our examples using let, so our first example becomes:

(defun printtwice()
  (let ((val (read)))
      (display val)
      (display val)))

The only real difficulty I have had is explaining why there are two parenthesis around ((val (read))) instead of one. Examples involving more than one name defined by the let statement show the students why it is necessary in order for the computer to understand their code, but even so they have a tendency to forget them.

Advertisements

Posted in Teaching Scheme | Leave a Comment »

A Comparison Between Scheme and Common Lisp

Posted by Peter on March 11, 2006

Before putting down my ideas on why I prefer Scheme over Common Lisp I did a brief internet search on the subject, but there was very little comparison between the two. I did find plenty of comparisons to other languages, but as I am not going to beat a dead horse by telling you why I think Lisp is great there is no need to go into what I have found.

And before you get a false impression I would like to stress that I think both Scheme and Common Lisp are excellent languages. Also I am comparing Common Lisp to PLT Scheme specifically. Now with that out of the way lets get into the details

Advantages of Common Lisp:
More features: If you have read my blog you will notice that I am often implementing in Scheme features found in standard Common Lisp, such as defun and destructuring-bind. Although it is fun and educational it shouldn’t really be necessary.

Macros: Macro definitions in Common Lisp are much simpler and intuitive than those you write in Scheme. Since macros are one of the key features that make Lisp such a powerful language this is a big advantage over Scheme. The problem with Scheme macros is that the clean and simple syntax for macro definitions only handles basic transformations. As soon as you need to do something complicated, for example inspection of any of the macro’s parameters, life is no longer clean or simple. In Common Lisp however the most complicated aspect of macros is avoiding unwanted variable capture, and to be honest with a little practice using gensym it isn’t that hard.

Documentation: I can’t say enough good things about the books and online documentation for Common Lisp. Scheme on the other hand is, in my experience, poorly documented. To be honest Scheme’s documentation for new users is excellent. However complicated or advanced features are poorly documented. The PLT language manual, while useful, is a notorious offender in terms of being difficult to understand and leaving things out.

Libraries, user base: Common Lisp is obviously ahead here.

Advantages of Scheme:
Simpler: Wait didn’t I say that more features was better? Well there is a downside to having many features, it makes programs that exploit those rarely used corners of the language that much harder to understand.

Functions are really first class: Although Common Lisp is a functional language it makes programming functionally much harder than Scheme. For example to call a function that was returned as a result you have to use the funcall expression. Likewise special operations are required to access the function value of a variable. This seems unnecessary to me.

Continuations: Scheme has them, Common Lisp doesn’t, end of story. Continuations are extremely powerful and useful. I sometimes compare continuations to macros, because like macros you don’t know how powerful they are until you start using them.

Editor: My one failing in life may be that I am not an emacs fan. Personally I find emacs unnecessarily complex. So this point is really a matter of personal preference, but Dr. Scheme, my editor/environment of choice is a pleasure to program in. It also makes introducing people to Scheme that much easier.

Conclusion:
You already know what I am going to say here, I like Scheme better. My two selling points were basically the editor, which made it easy to get going right away with Scheme and continuations. I haven’t blogged yet about continuations, but rest assured that I will, as they may be almost as important as macros.

Update: I have found one comparison here, and this one seems to come to the conclusion that Common Lisp is generally better. Bah!

Posted in Common Lisp | Leave a Comment »