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