"cond","and" and "or" in Scheme

25,786

Solution 1

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.

Solution 2

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).

Share:
25,786
babel92
Author by

babel92

Updated on October 15, 2020

Comments

  • babel92
    babel92 about 3 years

    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.