SCHEME setenv MITSCHEME_LIBRARY_PATH .:/package/scheme-7.2/lib %scheme SYNTAX - Pure lambda calculus - Constants, Primitives - Conditional - Lists [(), cons, car, cdr] - Let, Letrec - Definitions - Recursion REDUCTION RULES EXAMPLES - factorial, gcd, sum, Taylor Series, Fib Lists - length, append, reverse, fast reverse Latent Types Higher-order - map TYPE-FREE or LATENT TYPES? In Pure Calculus, every term is a function - just beta-reduction - no fixed reduction order - reduce to normal form - No errors possible In Scheme, - Primitive Data types (constants, operators) (new reduction rules) - Fixed Reduction Strategy o call-by-value o evaluated applications must be valid procedure calls: correct number and type of arguments - Reduction to a weak-normal-form - Errors possible Types: Is Scheme typed or untyped? It's Latently typed. Valid Programs include (+ 3 #t) The type of a result of an expression is not predictable: (if (> x y) 3 #t) The presence of a runtime type error cannot be predicted: (+ (if (> x y) 3 #t) 4) Number of arguments can even vary: (define plus) (lambda l e) (define pl (lambda l (if (null? l) 0 (+ (car l) (apply pl (cdr l)))))) Datatypes? None, though some extensions to Scheme support records which provide minimal support for abstraction Conclusion: Scheme is a primitive/simple functional language that provides the programmer with great flexibility Scheme: Programs and Data Program Syntax: (lambda (x) E) | (E .... E) (if E E E) | (cons E E) | (quote E) Symbols: 'E --> E Data Syntax: S-lists: Sym ::= symbols/identifiers Slist ::= ( S* ) S ::= Sym | Slist Examples - (quote (lambda (x) x)) (car (quote (lambda (x) x))) APPLY - builtin function takes a function and list of args and calls the function on the args MAP for unary functions: (define map (lambda (f l) (if (null? l) () (cons (f (car l)) (map f (cdr l)))))) (map (lambda (x) (+ x 1)) '(1 2 3 4)) MAP for n-ary functions: (define map (lambda (f l) (if (null? l) () (cons (apply f (car l)) (map f (cdr l)))))) (map (lambda (x) (+ x 1)) '((1) (2) (3) (4))) (map + '((1 2 3) (2 4 6) (3) (4 4 4 4))) Environments: the-environment - function that returns the current environment system-global-environment - builtin environment with system primitive user-initial-environment - current toplevel environment nearest-repl/environment - function that returns most recent environment Eval - (eval EXPRESSION ENVIRONMENT) - Evaluates EXPRESSION, a list-structure representation of a Scheme expression, in ENVIRONMENT. (define foo (list '+ 1 2)) (eval foo (the-environment)) => 3 ((eval (list 'lambda '(x) 'x) user-initial-environment) 3) Define APPLY using EVAL: (define apply (lambda (f l) (eval (cons f l) user-initial-environment))) We can write Scheme programs that manipulate/generate other Scheme Programs. IMPACT OF THIS: o We can write a simple Scheme interpreter in Scheme: Define the following functions: eval - takes an s-expression and an environment (list of association pairs) and returns value of exp. apply - takes a function name or description, a list of args, and an environment, and applies the function to the args rep - implements the read-eval-print loop of a Scheme interpreter. Takes no args. * reads in s-expression * determines if definition or expression * calls eval to evaluate expression * updates current top-level environment if def o We can write programs that can change dynamically. AI programs may require adaptive behavior or some learning component. - Perhaps we have a knowledge base that consists of a set of rules/functions represented as s-expressions We can extend this knowledge base by constructing new functions as data structures. o We can write self-applicable programs (Partial Evaluation): Partial Evaluation - Suppose we have a function f(x,y) of two argument - Assume given a value for x (x=v) - We can consider defining a specialized version of f, fv, such that f(v,y) = fv(y): we have specialized f by fixing the value of x, with the goal of performing reductions/ operations that are independent of y: - This is partial evaluation: f(x,y) = if x>0 then y else -y - Now consider the case where f is an interpreter for a language: f(p,d) {p = input program; d = input data} - We can partially evaluate f with respect to a given program: the result is a "compiled" version of the program fp - Let PE be a partial evaluator, I an interpreter, P a program PE(I,P) is an object program P': I(P,D) = P'(D) PE(PE,I) is a compiler C: C(P) = P', I(P,D) = P'(D) PE(PE,PE) is a compiler-compiler CC CC(I) = C, C(P) = P', I(P,D) = P'(D) - SIMILIX (A. Bondorf, Copenhagen) is a partial evaluator for Scheme, written in Scheme.