On 2012-09-05, Yves S. Garret <
yoursurr...@gmail.com> wrote:
> So I'm going through gigamonkeys, this chapter:
>
http://gigamonkeys.com/book/macros-defining-your-own.html
>
> I get to the following snippet.
>
> (do-primes (p 0 (random 100))
> (format t "~d " p))
>
> |
> |
> v
>
> CL-USER> (macroexpand-1 '(do-primes (p 0 (random 100)) (format t "~d " p)))
> (DO ((P (NEXT-PRIME 0) (NEXT-PRIME (1+ P))))
> ((> P (RANDOM 100)))
> (FORMAT T "~d " P))
> T
>
>
>
> If I understand this correctly, the reason why random is run every time the
> do loop is run is because (random 100) is passed into the macro unevaluated
> and then put in place where the upper limit of the do-primes macro is
> supposed to do, yes?
random is called on every iteration simply because the macro wrote the code
that way. Once you see the expanded code, you can just think about the expanded
code (if you want). The code is what it is, and evaluates the expression
(random 100) on each iteration.
The macro took the piece of source code denoted by (random 100) and stuck it
into the DO loop form in that way.
The form could be placed into the DO loop in a different way such that it
is just evaluated once. If, in a DO variable binding you only have a
single expression, rather than two, then instead of stepping, you get
a one time initialization.
(do ((r100 (random 100))
(p (next-prime 0) (next-prime (1+ p))))
((> p r100))
...)
So it is all about how you stick that piece of code into the target
code template: what evaluation rules that piece of code is subjected to.
Problem is now that the body of do-primes has visibility to a variable
called r100 which does not appear anywhere in the do-primes syntax.
If the user happens to be using a variable called r100, there is a clash.
To do this right, we would have the macro invent a new uninterned symbol by
calling gensym, and insert that symbol instead of r100.
> So, when the macro is run, the only time that the loop
> ends is when it gets to a point where a random number is generated is less
> than the iterated number and the loop exits, yes?
Of course, this is indistinguishable from getting a single random number.
You're just wasting machine cycles on getting unnecessary random numbers.
The probability that, on any given iteration, the loop will end, is exactly the
same whether you pick a new number each time, or stick with one initially
chosen random number.
> Also, how often would you say you use macros when writing Lisp code professionally or just in general?
It's nearly impossible to write Lisp code without *using* a macro, such as
DEFUN. You benefit from using other people's macros, including the ones in the
language, even if you do not write any of your own. Outside of the language
proper, you will find that many libraries will have useful macros.
How often do you write your own macros? Quite a lot, possibly.
Any time you have some repeating tedious coding pattern with some variation,
there may be a macro hiding in there wanting to unify and condense it all.
Any nontrivial Common Lisp program is usually going to have some fraction of
its code represented by macros, unless it's written by someone who wants to
avoid macros at all costs. A good way to answer this question might be to
sample some open source Lisp projects, looking for "macro": calls to defmacro,
symbol-macrolet, macrolet, define-symbol-macro and define-compiler-macro.
--
If you ever need any coding done, I'm your goto man!