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 user$f@a2268a>
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)))))