473,813 Members | 3,448 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

merits of Lisp vs Python

How do you compare Python to Lisp? What specific advantages do you
think that one has over the other?

Note I'm not a Python person and I have no axes to grind here. This is
just a question for my general education.

Mark

Dec 8 '06
852 28833


greg wrote:
Ken Tilton wrote:
>The last example showed the macro inserting code to magically produce
a binding inside the reverse function.


Are you sure? It looked to me like it was adding code *around*
the reverse function, not inside it. I posted a Python function
that achieves the same thing by calling the existing reverse
function.
You are thinking about the results iteration, where you broke
encapsulation. I just reminded you of the magical "signed-value" binding
in a reply to another post of yours.

btw, when looking back at the rest of the code I was reminded I had done
something even wilder (well, maybe as wild) in the transforming code
itself. I say "wilder" in the sense of it being waaaaay cool, having a
flying-without-a-net feeling, yet making coding of dozens and dozens of
these transformations simpler, terser, and less buggy.

Someone had me laughing when they said the actual application of a macro
was nice and simple, but the macro itself was scary. It reminded me of a
cranky but sweet old guy on a project who was outraged upon learning I
was using a finite state machine to handle a shaky exchange between two
processes. He maintained that I was "foisting a crazy scheme on the
bank" which no one would be able to maintain. He actually forced me to
defend it in a group code review, the first they ever had, so don't
think it was a normal process for them, this was war. After my
demonstration on how the FSM would react to either or both processes
going south at any point in the exchange, the crank pronounced his
satisfaction with the approach and said, "OK, that is simple. The
infinite-state thing is complicated, but the way it works is simple."
That really made the whole thing worthwhile. :)
I'm still trying, but some of the code you posted is rather
impenetrable without knowing a lot more about the details of
your system. I'm doing my best to show some Python demonstrating
the gist of what could be done.
Great. That's the spirit. But how do we move forward if you just express
global confusion? See if you can understand the magical binding of the
parameter "signed-value". The reverse function will be called by the
engine to reverse a mathematical transformation, in this case simply
taking the absolute value. The generic engine has no way of knowing out
of all the targets, results, and operands (targets from a "before"
expression relocated in their incarnation in the expression operated on)
recorded by a transformation to pass in that position. When I code that
reverse function, I just want to work on the signed-value, as identified
in hard-code fashion by the transformation. ie, All I need do is
coordiate the TF and its reverser. If the reverser needs something else,
say the "coefficien t" (this would be a add-like-terms TF), I just go to
the add-like-terms and have it tag the coefficients with the symbol
'coefficient, then I can code:

(reverse (coefficient literal-part)...)

Ah. Time to refactor. I will have multiple coefficients, and when
multiples are expected I want all the input math forms searched for
those tagged coefficient. Any ideas out there? :) It is so tempting to
add an s and have the macroexpansion look for a trailing s in the
symbol-name, but then I am bound to have some singular and in s. Ah,
grep to the rescue: (reverse (literal-part coefficient+).. .)

Sweet. By using + I can even have the macroexpansion insert an assertion
that there is at least one. Of course there should be at least two or
this TF would not fire. And so it goes...

:)

ken

--
Algebra: http://www.tilton-technology.com/LispNycAlgebra1.htm

"Well, I've wrestled with reality for thirty-five
years, Doctor, and I'm happy to state I finally
won out over it." -- Elwood P. Dowd

"I'll say I'm losing my grip, and it feels terrific."
-- Smiling husband to scowling wife, New Yorker cartoon
Dec 15 '06 #691
Christophe Cavalaria <ch************ *@free.frwrites :
def nif(num, pos, zero, neg):
return (zero, pos, neg)[cmp(num, 0)]
Owwoooooooooo!! !
Dec 15 '06 #692
Paul Rubin wrote:
>
"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.
You can use that style in CL.

(defun nif (x p z n)
(or (when (< x 0) n)
(when (= x 0) z)
(when (x 0) p)))
Wade
Dec 15 '06 #693
Paul Rubin schrieb:
André Thieme <ad************ *************** *@justmail.dewr ites:
>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é
--
Dec 15 '06 #694
Christophe Cavalaria schrieb:
Paul Rubin wrote:
>André Thieme <ad************ *************** *@justmail.dewr ites:
>>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]
Since we are in one liners, let's be even smarter and do it like that :

def nif(num, pos, zero, neg):
return (zero, pos, neg)[cmp(num, 0)]
Okay, that reduces the complexity of the Python version to that of Lisp.
Now both have the same token count.
André
--
Dec 15 '06 #695
Wade Humeniuk <wh************ ****@telus.netw rites:
"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.

You can use that style in CL.

(defun nif (x p z n)
(or (when (< x 0) n)
(when (= x 0) z)
(when (x 0) p)))
Yeah but you can't apply it the same way.

[nif x p z n | x <- [0,2.5,-8]]

evaluates exactly one of p, z, or n, for each of the args in that
list. Side effects don't work the same way either, you have to use
special declarations around code with side effects. I'm not yet
conversant enough with Haskell to know how to do it for this example
though.
Dec 15 '06 #696
André Thieme <ad************ *************** *@justmail.dewr ites:
and the Lisp version has only 9:
nth, 1+, truncate, signum, num, list, pos, zero, neg
Oh come on, you have to count the parentheses too.

Anyway, token count doesn't mean much, you have to instead go by the
user's cognitive effort in dealing with the prefix notation etc.,
which isn't purely a matter of token count. And if (+ 2 3) were
really as easy to read as 2+3, mathematics would have been written
that way all along.
TypeError: 'str' object is not callable
I don't know how I can fix that. Maybe you could tell me.
>>lazy_nif(0, lambda: "p", lambda: "z", lambda: "n")
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?
There's a Haskell builtin called 'seq' which forces evaluation but
again I'm not sure precisely how to apply it here.
Dec 15 '06 #697
Paul Rubin <http://ph****@NOSPAM.i nvalidwrites:
André Thieme <ad************ *************** *@justmail.dewr ites:
>and the Lisp version has only 9:
nth, 1+, truncate, signum, num, list, pos, zero, neg

Oh come on, you have to count the parentheses too.
No. Parentheses are editor commands. They don't count anymore than
spaces "count" in Python.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"You question the worthiness of my code? I should kill you where you
stand!"
Dec 15 '06 #698


xs*****@gmail.c om wrote:
Ken Tilton wrote:
>>Andrew Reilly wrote:

>>That all looks like data.

No, not reverse, the part you did not understand. I do not mean what the
code was doing, I meant that it was code.


Code is data is code
I was hoping no one would make that mistake. :) macros are all about
code is data, but code is not data in Python* so the two words code and
data serve to differentiate them for Pythonistas.

* Taking questions after a keynote to ILC200? where he reiterated that
Python was the same as Lisp for all intents and purposes:

Norvig: "Yes, John?"
McCarthy: "Is code also data in Python?"
Norvig: "No."

End of exchange. :)
>- even in Python:
This could be tougher than I thought.
>
skills_table = [
{
"title": "Absolute Value",
"annotation s": ["Bleah bleah", "ho hum", "etc..."],
"hints": ["and so on", "etc..."],
"reverse" : (lambda x: whatever(x))
That does not demonstrate that code is data, that demonstrates that a
lambda is a first-class object (and, yes, Python's lambda is lame).

You will know you have code as data when you can write Python code that
takes apart "whatever(x )" and produces "oh-now-I-get-it(y)". As part of
the language, such that Python applies your transforming code for you
whenever it sees whatever. (Hell, even C has a preprocessor.)
},
{
"title": "Square Root",
"annotation s": ["Bleah bleah", "ho hum", "etc..."],
"hints": ["and so on", "etc..."],
"reverse" : (lambda x: someother(x))
},
# etc...
]

Of course those lambdas are crippled in Python (and not really
necessary in this bogus example)... But that's without trying to be
clever:

class AbsoluteValue:
title="Absolute Value"
annotations=["Some list", "goes here"]
@classmethod
def reverse(cls, *args):
# I didn't understand what your code was doing
yeah, and god forbid you should ask. :) this is the crux of the matter!

Actually, it is kinda cool that you and Greg are semi-identifying the
crux by saying "this is the only bit I do not get, I'll skip this, move
on, nothing to see here".
pass
defskill(Absolu teValue)

That would be a reasonable place for a "pie decorator" on a class, but
I guess that's not allowed.
Hmmm. Actually, that is the whole point, all of Python is allowed.
decorators were used in PyCells, but I never got much of an idea what
they did. Is there a moral equivalent of a macroexpansion for decorators
so you can show the before and after?

I doubt this second example would be
considered "Pythonic" in any case...
exactly what we are looking for in this cultural exchange: how would
Python handle what I am doing with macros in the reverse functions? Make
it as slick and programmer-friendly (cuz I may get to a hundred of these
before I am done with Algebra I) as possible. When all the Pythonistas
proclaim it optimal, then we compare and contrast.

This, btw, is the Tilton Test for language comparison: Not measurements
of programmer effort, rather examination of perfect equivalent code.
PyCells vs Cells would be an amazing case, because that is some hairy
functionality.
>>Not the code. In reverse.
Why not?
Is, too! (ie, I am kinda looking for a specific question that conveys
understanding of the use case.)
Python has plenty of other flaws that I can't happily work around, and
I do think Lisp is more flexible. However, I think your example is
readable enough with a data driven algorithm in most any popular
language. All of the data is visible to the reverse(...) method.
Maybe I missed something in your example, but I think you aren't trying
hard enough. :-)
Precisely. I am not trying at all. I am coding between visits to Usenet.
This use case just popped up and was pretty simple (at first, before I
got to the reverse function) so I dropped it off. This is a wild macro,
not farm-bred, deliberately crafted to embarrass macro. A real live
natural comes up all the time working wouldn't want to code without it
macro. I could have searched my code base to find more brutal cases, but
this is short and sweet and unforced and uncontrived and wheres my
thesaurus?
ken

--
Algebra: http://www.tilton-technology.com/LispNycAlgebra1.htm

"Well, I've wrestled with reality for thirty-five
years, Doctor, and I'm happy to state I finally
won out over it." -- Elwood P. Dowd

"I'll say I'm losing my grip, and it feels terrific."
-- Smiling husband to scowling wife, New Yorker cartoon
Dec 15 '06 #699
Paul Rubin schrieb:
André Thieme <ad************ *************** *@justmail.dewr ites:
>and the Lisp version has only 9:
nth, 1+, truncate, signum, num, list, pos, zero, neg

Oh come on, you have to count the parentheses too.
We could define hundreds of way how to count tokens.
But see the program as a tree:

nth
/ \
/ \
/ \
1+ list
| / | \
| / | \
truncate pos zero neg
|
|
signum
|
|
num

And I didn't count the indentation level and \n in Python code.
Why should I? They are editor commands.

Anyway, token count doesn't mean much, you have to instead go by the
user's cognitive effort in dealing with the prefix notation etc.,
How complicated ss it to say "cmp(a, b)" compared to "a cmp b"?
After a few days writing Lisp code your brain specializes on that
style. Arabian countries write from right to left. They seem to have
no problem to use what they know.
I admit that I am used to write +, -, * and / infix, because I were
trained in that thinking since day 1 in school.
In our example program there was only 1+ compared to ".. + 1" which
looks "alien" to untrained people.
If a program uses extensive math we can get syntax for Lisp that is
even more pleasant to read than Pythons:
17a + x³-x²
which isn't purely a matter of token count. And if (+ 2 3) were
really as easy to read as 2+3, mathematics would have been written
that way all along.
Mathmaticians invented prefix notation and they use it regularily.
They inventey operators that wrap around their arguments, as one can
see here: http://www.mathe-trainer.com/formel/?SN=&t=1

Or think of indices, etc.
>TypeError: 'str' object is not callable
I don't know how I can fix that. Maybe you could tell me.
>>>lazy_nif(0 , lambda: "p", lambda: "z", lambda: "n")
Yes, that works. And that's why I wanted to make it a macro.
Now you are essentially doing what I did in my first Lisp version.
While this works it is farer away from what we think.

(nif 0 "p" "z" "n")
(nif 0 #'p #'z #'n)
are exactly what one thinks.
For this reason "if" is implemented as a keyword in Python.
It allows you to give code as a block instead of embedding it into
a lambda or a def (which even needs a name).
And we might go further (again with an easy Graham example).
See this typical pattern:

result = timeConsumingCa lculation()
if result:
use(result)

We need this ugly temporary variable result to refer to it.
If we could use the anaphor[1] "it" that could make situations like
these more clean.

Imagine Python would have an "anaphoric if", "aif". Then:

aif timeConsumingCa lculation():
use(it)

Many Lispers might have this as a macro in their toolbox after some
time of coding or after reading Graham.
A short three-liner in Lisp and I can really say:

(aif (timeConsumingC alculation)
(use it))

How would you solve this in Python?
You could embed it inside a lambda and must somehow make the
variable "it" visible in it, because in the context of aif this
"it" gets bound to the result.
>>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?

There's a Haskell builtin called 'seq' which forces evaluation but
again I'm not sure precisely how to apply it here.
I wouldn't wonder if there was an operator like "seq" to do that.
So in some languages that support functional programming one needs to do
extra work to get lazyness, while in Haskell one gets extra work if one
doesn't want it. But maybe someone can correct me here.
In Lisp one could build some features to get lazyness as well.
[1] http://en.wikipedia.org/wiki/Anaphora_%28linguistics%29

I hope this posting was not sent two times. I just sent it but it didn't
appear in my list after reloading.
André
--
Dec 15 '06 #700

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
2196
by: Paddy3118 | last post by:
This month there was/is a 1000+ long thread called: "merits of Lisp vs Python" In comp.lang.lisp. If you followed even parts of the thread, AND previously used only one of the languages AND (and this is the crucial bit), were persuaded to have a more positive view of the other language; (deep breath, this is a long, as well as grammatically incorrect sentence), THEN WHY NOT POST ON WHAT ARGUMENTS PERSUADED YOU.
0
9607
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10665
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10420
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10139
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9221
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7681
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6897
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5568
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3881
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.