Scheme Tutorial
modified from Jade Rubick
General Points about Scheme
* Everything is an expression
* Every expression has a value
* Almost every expression is a procedure call
Exceptions: variables, constants, syntax
* Strict evaluation
Ex: (+ 1 2) => 3
Ex: (+ (+ 3 4) a)
Ex: (sqrt 2)
Thus, arguments in a function are evaluated before they are called.
* At the end of the let expression a is erased (it is local):
(let ((a 3))
(sqrt a))
* (let (bindings)( body))
* Function:
(define square (lambda (x)(* x x)))
(define (square x) ; equivalent to above
(* x x))
(let ((square (lambda (x) (* x x))))
(square (sqrt 2))) => 2
(define foo (square 3))
(define (bar x)
(square x))
(define (odd? n)
(if (zero? n)
#f ; false
(even? (- n 1))))
(define (even? n)
(if (zero? n)
#t ; true
(odd? (- n 1))))
* It's okay to put things like ? in a procedure name. It is common to
put a question mark when the procedure tests true or false.
Numbers
3.14159 7 3/4 2+2i
Lists
'() <<>-empty list '(1 2 3) '(1 (2 3) 4) <<>-list inside list '(1 'foo)
Booleans
#t #f
Strings
"foo"
Vectors
'#(1 2 3)
Symbols
A symbol always stand for the same value, i.e. if a is a symbol
then a = a will always return true. This is different than for strings
where "a" = "a" is usually not required to return true since the
strings can reside at different locations in memory. Symbols are
therefore more efficient than strings.
Procedures
(lambda (x) x)
Scheme is not typed, so you don't have to specify whether x is an
integer, real, etc... The following statement in C:
int square (int x) {return x*x;}
Would be:
(lambda (x) (* x x)) in Scheme.
Characters
#\a
#\space
Lists are what LISP is most famous for, so we'll concentrate
on them with Scheme, a derivative of LISP
A list is empty or a pair:
(null? '()) => #t
(null? '(1 2 3) => #f
(pair? '()) => #f
(pair? '(1 2 3)) => #t
Why is it called a pair? Think back to linked lists. Each node in a linked
list in this case contains two pointers, one pointing to the contents of the
node (car) and one pointing to the next node or NULL pointer
(cdr).
'(a . b) '(1 2 3) is shorthand for
'(a) '(1 . (2 . (3 . ())))
You construct a list using cons.
(cons 'a 'b) => [ pointer to a : pointer to b ]
(cons 'a '()) => [ pointer to a : null pointer ]
(car '(1 2 3)) => 1
(cdr '(1 2 3)) => (2 3)
And if you're very ambitious, you can combine them together with cadr
(cadr '(1 2 3)) => 2
Alternately, use list:
(define c (list 'a 'b))
Get the first part of this with
(car c)
What does the following do?
(define length
(lambda (e)
(if (null? e)
0
(+ 1 (length (cdr e))))))
It finds the length of a list.
(cons 0 '(1 2 3))
=> (0 1 2 3)
Input/Output
(read) reads in a value (one full data element of any type)
(write e) writes out
(read-char) specifies you want to read in a character.
(load "foo.scm") loads a file.
Note: usually when you are writing a Scheme program, you type it in
emacs, and then mark the region around it, and use ESC-X scheme-compile-region
to run it.