“cond”,”and” and “or” in Scheme

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.

Leave a Comment