** 3. Scheme ** 3.1. A dialect of Lisp Salient features: * dynamically, strongly typed * expression-oriented, largely side-effect-free * functional * list-oriented, garbage-collected heap-based * highly regular and expressive "an executable version of the lambda calculus" Typically used with interactive read-eval-print loop, with interpreted implementation * rapid development of small programs * good debugging support Good compilers exist, too -------------------------------------------------- 3.2. Our focus: *) expression-oriented syntax *) dynamic typing *) lists & recursion *) S-expressions; meta-circular interpreters *) first-class functions *) continuations *) syntax extensions -------------------------------------------------- 3.3. Intro: Identifiers: x x1_2 is-string? make-string! <= Literals (self-evaluating expressions): 3 -4 0.34 -5.6e-7 "hi there" "" #t #f Operations, calls: Prefix syntax: (expr_fn expr_arg1 expr_arg2 ... expr_argN), N >= 0 Examples: (+ 3 4) --> 7 (+ 3 4 5 6) --> 18 (+) --> 0 (+ (* 3 4) (/ 8 2)) --> 16 (< 3 4) --> #t (> 3 4) --> #f=() *) syntax is "simple" & "regular" but not "natural"; is this good? +) no precedence & associativity rules +) more flexible #'s of arguments -) not as accessible Evaluation rule: evaluate fn & argument expressions, in some order, then apply fn value to arg values -------------------------------------------------- 3.4. Special forms: *) exceptions to the rule that evaluate all arguments first *) exception selected if "fn" expression is some special symbol *) special forms have their own rules for interpreting/evaluating remaining expressions Examples: (define sym expr) => don't evaluate sym, but create a new binding of sym to result of evaluating expr. creates binding in current scope. (+ seven eight) --> error; unbound variable (define seven (+ 3 4)) --> 7 (define eight (+ seven 1)) --> 8 (+ seven eight) --> 15 (if test-expr then-expr else-expr) => evaluate test-expr; if non-null (i.e. true), then evaluate & return then-expr, otherwise evaluate & return else-expr. Don't evaluate both then- and else-expr. It's an expression, not a statement (like ? : in C). (define x 0) (define y 10) (define z (if (= x 0) 0 (/ y x))) (define (fn-sym formal-sym1 ... formal-symN) expr) => define a function named fn-sym, with N formals named formal-symi, whose body is expr. When called on N argument values Vi, evaluate expr where each of the formal-symi is bound to the corresponding Vi. A special form, because don't evaluate either (fn-sym ...) nor expr. (define (fact n) (if (<= n 1) 1 (* n (fact (- n 1))))) --> fact (fact 10) --> 3628800 (fact -10) --> 1 How about absolute value? (define (abs x) (if (< x 0) (- x) x)) How about: (define (if-not test then else) (if (not test) else then)) What's wrong? => not a special form (if-not (= x 0) (/ y x) 0) --> "Division by zero signalled by /" -------------------------------------------------- 3.5. More special forms: cond: an if-then-elseif-then...-else chain: (define (signum x) (cond ((> x 0) 1) ((= x 0) 0) (else -1))) or and and are short-circuiting special forms: (or (= x 0) (> (/ y x) 10)) (and (> x 0) (> (/ y x) 10)) let: local variable bindings in a new scope *) binding expressions evaluated in order, but bindings happen after all evaluated *) a body expression (define x 1) (define y 2) (define z 3) (let ((x 5) (y (+ 3 4)) (z (+ x y z))) (+ x y z)) --> 5+7+(1+2+3)=18 let*: like let, but bindings visible in later binding expressions (define x 1) (define y 2) (define z 3) (let* ((x 5) (y (+ 3 4)) (z (+ x y z))) (+ x y z)) --> 5+7+(5+7+3)=27 let/let* typically used within function bodies -------------------------------------------------- 3.6. ** Summary ** *) no statement syntax, or control structure syntax *) no special infix/prefix operator syntax *) instead, regular expression syntax + special (evaluation) forms *) no need for "return" statement, if expr vs. if stmt; can declare temporary variables for use in evaluating an expression, not just a stmt *) variable names can have embedded punctuation; token boundaries defined by whitespace & parens