Call-by-reference ================= Let's make something to increment a variable. Know that the following approach (and its analogue in Java, Python, C, C++) doesn't work: (define (++ v) (set! v (+ v 1))) (define x 324) (++ x) (display x) ; displays 324 Pass `object' allowing access to variable ----------------------------------------- In C: // Type int*: address of an int / operator *: access int by address void inc(int* var) { *var = *var + 1; } int x = 324; inc(&x); // operator &: address of value // x now 325 In Scheme: ; var a procedure of 0-1 argument ; (var) gets value ; (var a) set value to a (define (++ var) (var (+ (var) 1))) (define x 324) (++ (lambda args ; gets arguments as a list (if (null? args) x (set! x (car args))))) (display x) ; displays 325 The lambda `captures' the *variable* x, not just its value. Can we write a procedure to make this lambda? (define x 324) (++ (& x)) ; same problem: passes value of x to & So make our own syntactic form. Want the literal code (& x) to mean literally the *code* (lambda args (if (null? args) x (set! x (car args))))) And more generally, the code (& ) ; notice we don't mean literally now to mean the code (lambda args (if (null? args) (set! (car args))))) where is any variable name. Here it is: (define-syntax & ; define-syntax makes a new syntactic form by specifying how ; to rewrite `calls' to & (syntax-rules () ; use the syntax-rules transformation language (there are others) ; notice it's not scheme: no general computation at runtime ; (no if, procedure call, let, etc), can be done at compile time ; as preprocessing step ; pairs of pattern and result ((& ) ; code pattern ; nothing special about <>, just common CS convention for non-literal code ; and reminding you that *code* will be attached to these, not values ; code template: code gets substituted (lambda args (if (null? args) (set! (car args))))))) Now: (define x 324) (++ (& x)) (display x) ; displays 325 Call-by-need ============ Let's make while looping. Know that the following approach (and its analogue in Java, Python, C, C++) doesn't work: (define (while condition body) (if condition (begin body (while condition body)))) (while #f (display 'hi)) ; evaluates arguments, so displays hi once (while #t (display 'hi)) ; evaluates arguments, so displays hi once Instead, want (while ...) to be as if we had written: (letrec ((w (lambda () (if (begin ... (w)))))) (w)) So: (define-syntax while (syntax-rules () ((while ...) ; ... means 0 or more expressions (letrec ((w (lambda () (if (begin ... (w)))))) (w))))) For example: (define (sum-of-squares n) (let ((i 1) (s 0)) (while (<= i n) (set! s (+ s (* i i))) (set! i (+ i 1))) s)) Here's a Python-like for: (define-syntax for (syntax-rules (in) ; makes `in' a keyword, will only match `in' ; not an arbitrary piece of code like and ((for in ...) (for-each (lambda () ...) )))) (for x in '(3 2 4) (display x)) ; displays 324