merits of Lisp vs Python

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


Paul Rubin schrieb:
> André Thieme <address.good.until.2006.dec.22 at justmail.de> writes:
>> def nif(num, pos, zero, neg):
>>    if num > 0:
>>      return pos
>>    else:
>>      if num == 0:
>>        return zero
>>      else:
>>        return neg
> 
> def nif(num, pos, zero, neg):
>    return (neg, zero, pos)[cmp(num, 0)+1]

That is a nice idea. I can do the same in Lisp, but have to do it
without syntactic sugar which makes it longer, characterwise:

(defun nif2 (num pos zero neg)
   (nth (1+ (truncate (signum num)))
        (list pos zero neg)))

What Python has is cmp. That is doing what truncate+signum do in
Lisp. So that makes the biggest difference. Another one is that Lisps
signum keeps the datatype:
cmp(5.3, 0)  => 1
(signum 5.3) => 1.0

Or also with complex numbers [syntax #C(real, img)]:
(signum #C(10 4)) => #C(0.9284767 0.37139067)

Anyway, from the complexity the Lisp version is a bit better.
The Python version has 11 tokens:
return, tuple-reference, comma, neg, zero, pos, +, 1, cmp, num, 0

and the Lisp version has only 9:
nth, 1+, truncate, signum, num, list, pos, zero, neg

(I didn't count the function head, because both have the same
token count).



>> 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))
> 
> in Python:
> 
>     def lazy_nif(num, pos, zero, neg):
>        return (neg, zero, pos)[cmp(num, 0)+1]()   # the () at the end means funcall
> 
>     map(lambda x: lazy_nif(x, p, z, n), (0, 2.5, -8))

We could do the same in Lisp:

(defun lazy-nif (num pos zero neg)
   (funcall (nth (1+ (truncate (signum num)))
            (list pos zero neg))))

Here the token count is 12py vs 10cl.
CL-USER> (mapcar #'(lambda (x) (lazy-nif2 x #'p #'z #'n))
		 '(0 2.5 -8))

"no no"
"very negative"
"very positive"
("zero" "negative" "positive")

But there is a disadvantage:
 >>> lazy_nif(0, "p", "z", "n")
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 2, in lazy_nif
TypeError: 'str' object is not callable

I don't know how I can fix that. Maybe you could tell me.
In Lisp I would just go with the macro. That works for all cases.


> "nif" is even cleaner in Haskell, if I have this right:
> 
>     nif x p z n | (x < 0) = n
>                 | (x == 0) = z
>                 | (x > 0)  = p
> 
> All Haskell evaluation is automatically lazy, so no lambdas etc. needed.

Yes, that was what I already supposed.
Do you also know how I can "deactivate" lazyness?


André
-- 



More information about the Python-list mailing list