merits of Lisp vs Python

André Thieme address.good.until.2006.dec.22 at justmail.de
Fri Dec 15 09:16:16 EST 2006


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é
-- 



More information about the Python-list mailing list