Scheme
Reading: The Scheme Programming Language, 2.1–8, 3.2
Scheme is part of the Lisp family of languages, which also includes Common Lisp, a standardization of Lisp (partially influenced by Scheme); Emacs Lisp, the extension language used by Emacs; and Clojure, which many of you learned in Programming Paradigms.
Running Scheme
Scheme has a large number of not-completely-compatible implementations. We are using Chez Scheme, which is reputed to be very fast, and goes with the book we are using.
It is installed on studentnn.cse.nd.edu
, where
nn
∈ {04,05,06,10,11,12,13
}, at
~dchiang/Public/pl/bin/scheme
. To install it on your own
computer, you can probably use one of these commands:
sudo apt-get install chezscheme
brew install chezscheme
sudo port install chez-scheme
Now create a file called hello.scm
:
#!/usr/bin/env scheme --script
(display "Hello, world.\n")
To run it, make sure that scheme
is in your
PATH
, and type
scheme --script hello.scm
or make it executable and run it directly:
chmod +x hello.scm
./hello.scm
The Scheme language
I’d like you to take away three main ideas from this reading:
Lists
Scheme is a dialect of Lisp, which originally stood for List
Processor. Lists are the workhorse data structure in Scheme (more so
than in Clojure, which you may be more familiar with), so please get
familiar with them and their associated functions with their weird names
(cons
, car
, cdr
, etc).
Scheme expressions are also lists (which is what gives Scheme syntax
its characteristic appearance with lots of parentheses). This has
interesting implications for things like macros, which we won’t delve
into. But please be sure you understand the difference between
(+ 1 1)
and '(+ 1 1)
.
Functions
lambda
expressions are known as “anonymous functions” in
some other languages, and we also sometimes call them
abstractions. We’ll be using them all semester long, so be sure
you understand them well.
An important issue is that of lexical (or static) scoping. The Scheme book explains this in the paragraph starting “What happens when the procedure….” It goes by very quickly, so please pay very careful attention to it.
Recursion
Recursion plays a much more prominent role in Scheme and other functional programming languages than it does in imperative languages. The book gives three ways of defining recursive functions:
define
is for top-level (global) definitions of functions, which can be recursive;letrec
is for local definitions of functions that can be recursive; and- named
let
, which is similar toletrec
, but is sometimes more convenient in situations where you might use a loop in an imperative language.
The book spends a while talking about tail recursion, which
is important to know about for practical Scheme programming. (If you’re
coming from Clojure, this is a major difference: since the JVM does not
allow tail recursion, neither does Clojure; instead, the only way to
write efficient loops is using loop/recur
, which is similar
to named let
.)