merits of Lisp vs Python

William James w_a_x_man at yahoo.com
Fri Dec 15 13:25:52 EST 2006


André Thieme wrote:
> 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.

def p
  puts "very positive"
  "positive"
end
def z
  puts "no no"
  "zero"
end
def n
  puts "very negative"
  "negative"
end
def nif num, pos, zero, neg
  send( num>0 ? pos : (num==0 ? zero : neg) )
end

[0, 2.5, -8].map{|x| nif x, :p, :z, :n}

###  Another way #####

p = proc {
  puts "very positive"
  "positive" }
z = proc {
  puts "no no"
  "zero" }
n = proc {
  puts "very negative"
  "negative" }
def nif num, pos, zero, neg
  ( num>0 ? pos : (num==0 ? zero : neg) ).call
end

[0, 2.5, -8].map{|x| nif x, p, z, n}




More information about the Python-list mailing list