greg schrieb: > Ken Tilton wrote: > >> The reason I post macro expansions along with examples of the macro >> being applied is so that one can see what code would have to be >> written if I did not have the defskill macro to "write" them for me. > > It seems to me your brain is somewhat stuck on the use of macros.
That you see it this way is normal. A BASIC programmer would tell you the same thing. He can show you solutions that don't use classes, methods or functions. Some sweet gotos and gosubs are enough. The idea is that macros save you tokens and allow you to experess in a clearer way what you want to do. But in no case one "needs" them to solve a programming problem. All what Kenny showed could be done without his macro. It would just be a bit more complicated and the resulting code wouldn't look good. > You're looking at the expansion of your > macro and assuming that you'd have to write all that > code by hand if you didn't have macros. You're not > thinking about alternative approaches, which could > just as well be used in Lisp as well as Python, that > are just as compact yet don't make use of macros. He wouldn't have to write the full expansion. With functional programming he could also solve it, but then he would need a funcall here, a lambda there. And his code would not look so understandable anymore, because it is filled up with some low level details. I will take one of the first macro examples form "On Lisp". Let's say for some reason you want to analyse some numbers and do something depending on their sign. We want a function "numeric if": def nif(num, pos, zero, neg): if num > 0: return pos else: if num == 0: return zero else: return neg In Lisp very similar: (defun nif (num pos zero neg) (case (truncate (signum num)) (1 pos) (0 zero) (-1 neg))) Now one example Graham gives is: (mapcar #'(lambda (x) (nif x 'p 'z 'n)) '(0 2.5 -8)) which results in the list (Z P N). You can do the same thing in Python. But it gets hairier if we want to make function calls that have side effects. Let me add these three functions: (defun p () (print "very positive") "positive") (defun z () (print "no no") "zero") (defun n () (print "very negative") "negative") And now see what happens: CL-USER> (mapcar #'(lambda (x) (nif x (p) (z) (n))) '(0 2.5 -8)) "very positive" "no no" "very negative" "very positive" "no no" "very negative" "very positive" "no no" "very negative" ("zero" "positive" "negative") The messages were printed in each case. To stop that I need lazy evaluation: CL-USER> (mapcar #'(lambda (x) (funcall (nif x #'(lambda () (p)) #'(lambda () (z)) #'(lambda () (n))))) '(0 2.5 -8)) "no no" "very positive" "very negative" ("zero" "positive" "negative") I put the calls to the functions p, z and n into a function object. In some languages it would look a bit cleaner, for example Ruby. They have a single name space and don't need funcall and lambda is shorter. But still, we need to add several tokens. Maybe Haskell has built in support for that. Now with nif as a macro: (defmacro nif (expr pos zero neg) `(case (truncate (signum ,expr)) (1 ,pos) (0 ,zero) (-1 ,neg))) It is a bit more complex as the function. It has one ` and 4 ,s extra. But now we can express the problem very well: CL-USER> (mapcar #'(lambda (x) (nif x (p) (z) (n))) '(0 2.5 -8)) "no no" "very positive" "very negative" ("zero" "positive" "negative") And the first example also still works the same way. Now the expansion shows more code than we would have need to write ourself. However, now we can write code that matches much better how we think. No need for "low level" details like embedding the code inside of anon functions. This represents what most macros do. Save one or more lambdas and/or funcalls. One consequence is that development time gets cut down. André -- -- http://mail.python.org/mailman/listinfo/python-list