Final Exam Review Examples -------------------------- Pass By Name ------------ Pass by name is an unusual parameter-passing mechanism originally used in Algol. Consider this function:: int twice(int x) { // C++-like pseudocode x = 2 * x; } Suppose we call it like this using the variable ``vec[i]``:: twice(vec[i]); Then, if pass by name is used to pass ``vec[i]``, it's as if we had written this textually replaced ``x`` with ``vec[i]``:: vec[i] = 2 * vec[i]; Notice that this changes the value of ``vec[i]``, so it behaves a little bit like pass by reference. If the actual parameter in pass-by-name is the same as the name of a local variable in the function it is being passed to, then it must be renamed to avoid a conflict. An example of pass-by-name where this sort of substitution is not done is in the C pre-processor, which does purely textual substitutions with no concern for the names of other variables in the same scope. Sometimes, pass-by-name avoids the need to evaluate expressions, e.g.:: void f(float x, bool flag) { if (flag) { x = 2 * x; } } Using pass-by-name, it's possible that ``x`` is not evaluated, e.g.:: f(vec[i], false) // ... same as ... if (false) { vec[i] = 2 * vec[i]; } Evaluation of Lisp Expressions ------------------------------ Error messages have been simplified in the following transcript:: => (a) Error: Unable to resolve symbol: a in this context => (b) Unable to resolve symbol: b in this context => (quote a) a => (quote b) b => (quote quote) quote => (symbol? a) Unable to resolve symbol: a in this context => (symbol? b) Unable to resolve symbol: b in this context => (symbol? (quote a)) true => (symbol? (quote b)) true => (symbol? 'a) true => (symbol? 'b) true => (symbol? quote) ;; quote is a special form Unable to resolve symbol: quote in this context => (symbol? (quote quote)) true => (symbol? symbol?) false => (symbol? (quote symbol?)) true => (symbol? 'symbol?) true => (list? (1 2 3)) java.lang.Long cannot be cast to clojure.lang.IFn => (list? (quote (1 2 3))) true => (quote (1 2 3)) (1 2 3) => (list? '(1 2 3)) true => '(1 2 3) (1 2 3) => (quote (quote a)) (quote a) => (quote 'a) (quote a) => ''a (quote a) => (quote (quote quote)) (quote quote) => (quote 'quote) (quote quote) => ''quote (quote quote) => (list? quote) Unable to resolve symbol: quote in this context => (list? 'quote) false => (list? ''quote) true => (list? '''quote) true => '''quote (quote (quote quote)) => (first a) Unable to resolve symbol: a in this context => (first (quote a)) Don't know how to create ISeq from: clojure.lang.Symbol => (first 'a) Don't know how to create ISeq from: clojure.lang.Symbol => (first (quote (quote a))) quote => (first (quote 'a)) quote => (first ''a) quote => (rest (quote (quote a))) (a) => (rest (quote 'a)) (a) => (rest ''a) (a) => (first (rest ''a)) a => (rest (rest ''a)) () => (cons a (b c)) Unable to resolve symbol: a in this context => (cons 'a (b c)) Unable to resolve symbol: b in this context => (cons 'a '(b c)) (a b c) => (first (quote (quote a))) quote => (first (quote 'a)) quote => (first ''a) quote => (rest (quote (quote (quote a)))) ((quote a)) => (rest (quote (quote 'a))) ((quote a)) => (rest (quote ''a)) ((quote a)) => (rest '''a) ((quote a)) => (cons 'quote '((quote a))) (quote (quote a)) => (cons (first ''cat) (rest '''cat)) (quote (quote cat)) A Famous Lisp Quine ------------------- In programming, a Quine is a program that prints (or evaluates to) itself. Here is a Clojure_ Quine:: ( (fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x))) ) ) We've formatted it in a way to help show its structure. Lets try to understand what's going on here. First, note the expression has the form ``(f a)``, where ``f`` is a function and ``a`` is the argument passed into the function. So we can simplify it by using these two definitions:: (def f (fn [x] (list x (list (quote quote) x))) ) (def a (quote (fn [x] (list x (list (quote quote) x)))) ) ``f`` is a function, so when you evaluate it you get this:: user=> f # user=> (f 1) (1 (quote 1)) user=> (f 2) (2 (quote 2)) user=> (f 'a) (a (quote a)) user=> (f 'b) (b (quote b)) This makes it clear what ``(f e)`` does: it returns a 2-element list whose first element is ``e``, and whose second element is ``(quote e)``. We said the original Quine has the form ``(f a)``. That's true, but we can be more specific. It also has the form ``(f (quote f))``, i.e. it's a list whose first element is ``f`` and whose second element is ``(quote f)``. That's exactly the form of list that a call to ``f`` returns. Thus:: => (f (quote f)) (f (quote f)) This is a Quine: an expression that returns itself. The original Quine is now easily created by replacing ``f`` (in ``=> (f (quote f))``) with it's definition:: user=> ((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x))))) ((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))