Reputation: 777
I'm reading The Little Schemer. And thanks to my broken English, I was confused by this paragraph:
(cond ... ) also has the property of not considering all of its arguments. Because of this property, however, neither (and ... ) nor (or ... ) can be defined as functions in terms of (cond ... ), though both (and ... ) and (or ... ) can be expressed as abbreviations of (cond ... )-expressions:
(and a b) = (cond (a b) (else #f) and (or a b) = (cond (a #t) (else (b))
If I understand it correctly, it says (and ...) and (or ...) can be replaced by a (cond ...) expression, but cannot be defined as a function that contains (cond ...). Why is it so? Does it have anything to do with the variant arguments? Thanks.
p.s. I did some searching but only found that (cond ...) ignores the expressions when one of its conditions evaluate to #f.
Upvotes: 2
Views: 31972
Reputation: 48745
Imagine you wrote if
as a function/procedure rather than a user defined macro/syntax:
;; makes if in terms of cond
(define (my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))
;; example that works
(define (atom? x)
(my-if (not (pair? x))
#t
#f))
;; example that won't work
;; peano arithemtic
(define (add a b)
(my-if (zero? a)
b
(add (- a 1) (+ b 1))))
The problem with my-if
is that as a procedure every argument gets evaluated before the procedure body gets executed. thus in atom?
the parts (not (pair? x))
, #t
and #f
were evaluated before the body of my-if
gets executed.
For the last example means (add (- a 1) (+ b 1))
gets evaluated regardless of what a is, even when a
is zero, so the procedure will never end.
You can make your own if with syntax:
(define-syntax my-if
(syntax-rules ()
((my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))))
Now, how you read this is the first part is a template where the predicate consequent and alternative represent unevaluated expressions. It's replaced with the other just reusing the expressions so that:
(my-if (check-something) (display 10) (display 20))
would be replaced with this:
(cond ((check-something) (display 10))
(else (display 20)))
With the procedure version of my-if
both 10 and 20 would have been printed. This is how and
and or
is implemented as well.
Upvotes: 7
Reputation: 1
You cannot define cond
or and
or or
or if
as functions because functions evaluate all their arguments. (You could define some of them as macros).
Read also the famous SICP and Lisp In Small Pieces (original in French).
Upvotes: 1