I’m reading Paul Graham’s ANSI Common Lisp. In the chapter about macros he shows the following example:
(defmacro in (obj &rest choices)
(let ((insym (gensym)))
`(let ((,insym ,obj))
(or ,@(mapcar #'(lambda (c) `(eql ,insym ,c))
choices)))))
(Returns true if the first argument is equal to any of the other arguments)
He holds that it can’t be written as a function. Wouldn’t this function have the same functionality?
(defun in (obj &rest choices)
(reduce (lambda (x y)
(or x (eql y obj)))
choices
:initial-value nil))
The difference I see is that the macro will only evaluate arguments till it finds an eql argument. Is that it?
The point is, that the macro version evaluates the arguments lazily (it expands into an OR) stopping if a match is found. This cannot be achieved with a function, since a funcall will always evaluate all arguments first.