SchemeCOP Introduction to Scheme
SchemeCOP Scheme Meta-language for coding interpreters –“ clean ” semantics Scheme = LISP + ALGOL –simple uniform syntax; symbols and lists –block structure; static scoping –statement : evaluated for its effect –expression : evaluated for its value Dynamic type checking –flexible but inefficient (rapid prototyping)
SchemeCOP Expressions Literals Variables Procedure calls Literals numerals(2), strings( “ abc ” ), boolean(#t), etc. Variables Identifier represents a variable. Variable reference denotes the value of its binding. x 5 ref
SchemeCOP Scheme Identifiers E.g., y, x5, +, two+two, zero?, etc (Illegal) 5x, y)2, ab c, etc Identifiers –reserved keywords –variables pre-defined functions/constants ordinary functions = procedures
SchemeCOP Procedure Call (application) (operator-expr operand-expr...) –prefix expression (proc/op arg1 arg2 arg3...) Order of evaluation of the sub-expressions is “ explicitly ” left unspecified by Scheme. cf. C is silent about it. cf. Java specifies a left to right processing. (+ x (p 2 3)) ((f 2 3) 5 6)
SchemeCOP Special Forms Definition (define ) Conditional (if ) (define false #f) (if (zero? 5) 0 #t)
SchemeCOP Data Types values, operations, canonical representation Type-checking static : compile-time : efficient dynamic : run-time : flexible –numbers: +, -, *, number?, = etc –booleans: #t, #f, boolean?, etc –strings: string?, string->list, etc
SchemeCOP Symbols Identifiers treated as primitive values. Manipulated at run-time. –Distinct from identifiers that name variables in the program text. –Distinct from strings (sequence of characters). Meta-programming quote symbol?
SchemeCOP Lists Ordered sequence of elements of arbitrary types (Heterogeneous) operations –car, cdr, cons, null?,... –list, append,... –first, second,..., ninth
SchemeCOP Pairs (cons ’a ’b) (cons ’a (cons ’b nil) ) a b ab nil ()
SchemeCOP Equivalence Test (eq? (cons 3 ()) (cons 3 ())) #f (define a (cons 3())) (define b (cons 3 ())) (eq? a b) #f (define c a) (eq? a c) #t
SchemeCOP Vectors Both records and arrays provide random access to components. However, records are heterogeneous, while arrays are homogenoeus. Vectors are heterogeneous structures that provide random access to components using a computable index.
SchemeCOP Constructors and accessors (define v (vector 1 (+ 1 2))) #(1 3) (vector-ref v 0) 1 (vector-length v) 2 Index is 0-based.
SchemeCOP Procedures In Scheme, procedures are first-class objects. That is, they may be passed to or returned from procedures or stored in a data structure. (if (procedure? 3) car cdr) # (procedure? append) #t
SchemeCOP ( (if (procedure? procedure?) car cdr) (cons cdr car)) ’(list append)) = ( (car (cons cdr car)) ’(list append)) = (cdr ’(list append)) = (append)
SchemeCOP Apply -function (apply cons ’( x (y z))) = (cons ’x ’(y z)) = (x y z) (apply f ’(a1 a2... an)) = (f ’a1 ’a2... ’an) (apply )
SchemeCOP (apply apply (list procedure? (list apply))) = (apply apply [ proc-fn [ apply-fn ] ] ) = (apply proc-fn [apply-fn] ) = #t
SchemeCOP Anonymous Fucntions (lambda ) E.g., ( (lambda (n) (+ n 2)) 5) = 7 Evaluate actual argument expressions Bind these values to formals Evaluate body expression (static scoping)
SchemeCOP Variable Arity Procedures ( ) (append ’(1 (p q)) () ’(a b c)) (list ) (lambda ) is bound to the list of actual argument values supplied in a call.
SchemeCOP (define mul (lambda x (if (null? x) 1 (* (car x) (apply mul (cdr x)) ) )) ; 1 is identity w.r.t * ) ; assuming * is binary (mul 1 (+ 2 3) 5)
SchemeCOP Binding constructs in Scheme define binds value to a name. -function application binds formal parameters to actual argument values. let -constructs introduces local bindings –let –let* –letrec
SchemeCOP let -construct ( let ( (var1 exp1) … (varn expn)) exp ) exp1 to expn are evaluated in the surrounding context. var1,…,varn are visible only in exp. >(let ( (x 2) (y 7) ) y) >7
SchemeCOP >(let ( (x y ) (y 7) ) y) >*error* “ y ” undefined >(define y 5) >(let ( (x y ) (y 7) ) y) >7 >(let ( (x y ) (y 7) ) x) >5 >(let ( (y 7) (x y ) ) x) >5 (not 7)
SchemeCOP >(define y 5) >(let ( (y 7) (x y ) ) x) >5 >(let ( (y 7) ) (let ( (x y ) ) x) ) >7 >(let* ( (y 7) (x y) ) x) >7 let* abbreviates nested- let s. Recursive and mutually recursive functions cannot be defined using let and let*.
SchemeCOP letrec -construct ( letrec ( (var1 exp1) … (varn expn)) exp ) var1,…,varn are visible in exp1 to expn in addition to exp. > (letrec ( (x (lambda() y) (y (lambda() x) ) x )
SchemeCOP letrec -construct ( ) >(letrec ( (f (lambda(n) (if (zero? n) 1 (f (- 1 n)) )) ) ) (f 5) ) >1 >(letrec ( ( f (lambda () g) ) ( g 2 ) ) ( f ) ) >2
SchemeCOP boolean connectives (or test1 test2 … testn) (and test1 test2 … testn) or and and are not Scheme procedures. They use short circuit evaluation rather than traditional call-by-value.
SchemeCOP Branching constructs (cond (test1 exp1) (test2 exp2) … (testn expn) (else exp) ) (case key ( keylist1 exp1) ( keylist2 exp2) … ( keylistn expn) (else exp) )