I'm trying to learn Lisp but I got stuck by this example (you can find it on "ANSI Common Lisp", by Paul Graham, page 170):
(defmacro in (obj &rest choices)
(let ((insym (gensym)))
`(let ((,insym ,obj))
(or ,@(mapcar #'(lambda (c) `(eql ,insym ,c))
choices)))))
Graham then states:
The second macro [...]
in
returnstrue
if its first argument iseql
to any of the other arguments. The Expression that we can write as:
(in (car expr) '+ '- '*)
we would otherwise have to write as
(let ((op (car expr)))
(or (eql op '+)
(eql op '-)
(eql op '*)))
Why I should write a macro when the following function I wrote seems to behave in the same way?
(defun in-func (obj &rest choices)
(dolist (x choices)
(if (eql obj x)
(return t))))
I do not understand if I am missing something or, in this case, in-func
is equivalent to in
.
Function-like macro definition: An identifier followed by a parameter list in parentheses and the replacement tokens. The parameters are imbedded in the replacement code. White space cannot separate the identifier (which is the name of the macro) and the left parenthesis of the parameter list.
In the case of inline, the arguments are evaluated only once. Whereas in the case of macro, the arguments are evaluated every time whenever macro is used in the program.
2) In computers, a macro (for "large"; the opposite of "micro") is any programming or user interface that, when used, expands into something larger. The original use for "macro" or "macro definition" was in computer assembler language before higher-level, easier-to-code languages became more common.
No; since macros work at the syntactical or lexical level; they can be used in contexts where functions cannot; and can accept arguments that functions cannot.
The difference in using the macro vs function is in whether all the choices always are evaluated.
The expanded in
macro evaluates the choices sequentially. If it reaches a choice that is eql to the first argument, it returns a true value without evaluating any more
forms.
In contrast, the in-func
function will evaluate all the choices at the time the function is called.
The two other answers are correct, but to make things more concrete, consider this interaction:
CL-USER(1): (defmacro in ...)
IN
CL-USER(2): (defun in-func ...)
IN-FUNC
CL-USER(3): (defvar *count* 0)
*COUNT*
CL-USER(4): (defun next () (incf *count*))
NEXT
CL-USER(5): (in 2 1 2 3 (next))
T
CL-USER(6): *count*
0
CL-USER(7): (in-func 2 1 2 3 (next))
T
CL-USER(8): *count*
1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With