merits of Lisp vs Python

K

Ken Tilton

Robert said:
GUIs are a weak point, or were last I looked.

LW comes with CAPI, portable across the big 3. ACL has Common Graphics
on win32, and I think they have Gtk bindings elsewhere (just guessing,
really). Everyone has Ltk, Cells-Gtk, and Celtk. (Two Tks, one Gtk if
that is not clear).

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
 
N

Neil Cerutti

Neil said:
a = b[n]

with

(setf (aref a i) (aref b n))

and the attractions of Python may make more sense.

Here Python and Lisp are equal, 7 tokens vs 7 tokens, but in
Python one has to write less since "[]" are 2 chars while
"aref" are 4, plus the setf. But from counting the brain
units which I regard as an important factor they are both
equal.


A comparison of brain units of the above snippets is
irrelevant, since the snippets are not equivalent.

The Python snippet will work for any object a that provides
__setitem__ and any object b that provides __getitem__.

I don't know what an equivalent Lisp snippet would be (or even
exactly how close the above snippet comes to matching the
Python code), but whatever it is would be a better foundation
for comparing brain units with the above Python.


It would be exactly like the example given, just "aref"
replaced with something else. An example implementation:

==========================================
(defgeneric $ (container key))
(defgeneric (setf $) (value container key))

;;; Implementation for arrays

(defmethod $ ((container array) (key integer))
(aref container key))

(defmethod (setf $) (value (container array) (key integer))
(setf (aref container key) value))
==========================================

And usage:

==========================================
CL-USER(3): (defparameter a (vector 1 2 3 4 5))
A
CL-USER(4): ($ a 0)
1
CL-USER(5): (setf ($ a 0) 9)
9
CL-USER(6): a
#(9 2 3 4 5)
==========================================

The nice thing is, that you *can* dispatch on the container,
the key and the value.


That's cool. Thanks for posting the code.

Is the above 'duck-typing' idiom considered very useful to a
Lisper? It seems logical to me that duck-typing works best in an
environment where it is ubiquitous. If users have to implement
accessors specifically to use your library, it is not as good as
if they had already implemented one as a matter of routine.
 
J

josephoswaldgg

Bjoern said:
Cool, so in other languages I need to set block marks like () and {}
and also indent the code for readability, and in Python I indent
only. From my POV that's less work.

Try reading again. In Lisp, you use () and *your editor* automatically
indents according to the universal standard, or you leave it sloppy
until other folks reading your code convince you to get a proper
programming editor. Indentation does not get out of sync with semantics
because the editor virtually never misses parentheses that the Lisp
compiler sees. Expressions keep the same meaning even if you have to
start breaking them across lines, etc.

In Python, you group in your mind, and press indentation keys to make
it happen in your editor. The editor cannot help that much, because it
cannot read your mind. White space screwups in copy-paste cannot be
fixed by the editor automatically, because it cannot read the original
programmer's mind, and you have to fix it manually, and risk screwing
it up.
 
J

JShrager

Robert said:
I have the code here (probably not the latest bcs I left the company
when it was acquired), let's do a little experiment, for what it's
worth: 89727 lines of Lisp code in 131 modules (lisp code files), 3306
"(defun" (by grep|wc), and 261 "(defmacro". [We did NOT use macros as
functions!] [Note that lines of code doesn't really matter in Lisp.]

Wow--my emacs install has 1,152,598 lines of code in 1,570 files, 29,244
defuns and 1,393 defmacros. This really doesn't prove anything
whatsoever (as I imagine that your stuff was a _lot_ more complex),
except maybe how great the FSF is for giving away this sort of thing for
free.

Let us note that it's not FSF that gives this stuff away for free -- or
if it is them proximally, it is not them ultimately -- ultimately it's
the engineers who did all that work that gave it away for free.
 
N

Neil Cerutti

Try reading again. In Lisp, you use () and *your editor*
automatically indents according to the universal standard, or
you leave it sloppy until other folks reading your code
convince you to get a proper programming editor. Indentation
does not get out of sync with semantics because the editor
virtually never misses parentheses that the Lisp compiler sees.
Expressions keep the same meaning even if you have to start
breaking them across lines, etc.

Yes, it's the same way in Python. Of course, not everything is an
expression in Python, so it's not saying quite as much.
In Python, you group in your mind, and press indentation keys
to make it happen in your editor. The editor cannot help that
much, because it cannot read your mind. White space screwups in
copy-paste cannot be fixed by the editor automatically, because
it cannot read the original programmer's mind, and you have to
fix it manually, and risk screwing it up.

It is very easy a manual process, possibly as simple as selecting
the correct s-expr and pasting it into the right place in your
code.
 
B

Bill Atkins

greg said:
I'm not saying that it's impossible to compile
Python, only that's there's a lot more to it than
just macro expansion. The OP was saying something
like "If you added macros, you might get a compiler
for free", which is clearly far from true.

Yeah, my mistake - I simply glided right past the "just by macro
expansion." Oops. :)
Please correct me if I'm wrong, but as I understand,
getting efficient code out of a Lisp compiler requires
putting type declarations into the source.

If you put the same declarations into a piece of
Python code, then of course it would be fairly
straightforward to compile it efficiently. But it
wouldn't really be dynamic Python any more.

Type declarations can squeeze out extra efficiency, but vanilla Lisp
without type declarations will still beat Python, both because the
language is designed to compile well and because compilers for Lisp
are generally very mature. So it is not the case that type
declarations are the only thing that make Lisp efficient.
 
B

Bill Atkins

greg said:
Enough to know what I'm talking about. Tens
of thousands of lines of Lisp and Scheme, and
hundreds of thousands of lines of Python, I
would estimate.

Seeing as you asked, how much Python code have
you or Ken edited?

To be honest, very little Python code. But I have manually indented
and rearranged enough code in other line-based languages to appreciate
the convenience of s-expression-based commands.
 
B

Bill Atkins

Paul Rubin said:
The loop language is so complicated and confusing that I never
bothered trying to learn it. I always used simpler primitives to
write loops and it was always enough.

I think you're missing out. If you don't find LOOP appealing, look
for the ITERATE package. ITERATE is a more Lispy, more extensible
replacement for LOOP.
You can't really use that much recursion in Lisp because of the lack
of guaranteed TCO. I think that makes it reasonable to say that
Scheme is a functional language but Lisp is not. ("Functional" = it's
reasonable to code in a style where the only way to connect variables
to values is lambda binding (maybe through syntax sugar), so all loops
are implemented with recursion).

You should be pragmatic about this - I have never used a CL
implementation that didn't do TCO optimization (indeed, are there
any?). Although the standard doesn't require it, I treat it as a de
facto requirement and don't worry too much about it.
 
B

Bill Atkins

I V said:
To be a little provocative, I wonder if the idea that you're "talking to
the interpreter" doesn't apply more to lisp than to python; you can have
any syntax you like, as long as it looks like an AST.
Uhhh?

One of the things I've always found off-putting about lisp as that all the
syntax looks the same. In Algol-derived languages, each syntactic
construct has a fairly distinctive appearance, so when, for instance, I
encounter a for loop, I can quickly recognize that that's what it is, and
bracket out the "scaffolding" and pick out the details that interest me.
With lisp, I can't do that, I have to read through the sexp, decide on
what syntax it is, and then remind myself where to look for the relevant
specific details.

"Decide on what syntax it is"? Examples?
Now, this might well be just due to my comparative lack of familiarity
with lisp; I'd be interested to hear if you lisp people find different
lisp constructs as visually distinctive as constructs in python (or other
similar languages). But I think what people are getting at when they
complain about "all the brackets" in lisp may actually be this issue of
a visual distinction between different constructs (this is also a reason
why having a limited number of syntactic constructs can be helpful - there
are a probably a limited number of stereotypical layouts a programmer can
keep in their mind at once).

We rely on indentation for readability just as you guys do. Lisp
programs are not chaotic arrangements of parentheses and symbols; code
structure is made apparent through indentation.

(Why are people from c.l.p calling parentheses "brackets"?)
 
R

Robert Brown

Paul Rubin said:
Does this count as a "children of a lesser Python"? How does clpython
implement Python's immutable strings, for example?

http://dirtsimple.org/2005/10/children-of-lesser-python.html

I think CLPython is in the "children of a lesser Python" category, on the
grounds that it doesn't implement the complete language and there's no
obvious way to reuse the C packages that make CPython so useful. However,
the other distinguishing feature of the "children" category is bending
semantics to gain speed. CLPython doesn't appear to be doing much of this.
The author says it runs at about the same speed as CPython.

Python strings are implemented in CLPython as instances of a CLOS class, not
as raw Common Lisp strings, so they appear to be immutable.
 
J

JShrager

Speaking as the OP, let's see what the OP really said:
... compilers are GREATLY facilitated by having a
macro facility because (at first blush) all you need to do is to
macro-expand down to something you know how to turn into code.
This isn't the only, nor perhaps the best way to get a compiler, but it's
a step in that direction. Later on you can learn the other great
features offered by homogeneous syntax, like being able to write code
walkers, which help improve over the "first blush" compiler....

So, "If you added macros, you might get a compiler for free" is not a
fair paraphrase of this.

(Another way, BTW, that macros improve efficiency is by replacing
function calls with in-line code. Another cheap improvement facilitated
by macros.)
 
M

mystilleef

Paddy said:
In Python, most containers are directly iterable so we are much more
likely to arrange our program to use:
for a in y:
dosomethingwith(a)

-Paddy.

Or the more succinct Python (FP) construct:

map(dosomething, y)
 
R

Raffael Cavallaro

If you mistakenly select an extra parenthesis or omit one, it's
the same thing.

Because you can't mistakenly select an extra paren or omit one in a
lisp-aware editor. Whether its a commercial lisp IDE or emacs, you
don't manually select s-expressions. You put your cursor/point at one
paren and you tell the editor - with a keystroke or a mouse click - to
find the matching paren and select everything contained between the two.
 
P

Paul Rubin

Neil Cerutti said:
Is the above 'duck-typing' idiom considered very useful to a
Lisper? It seems logical to me that duck-typing works best in an
environment where it is ubiquitous. If users have to implement
accessors specifically to use your library, it is not as good as
if they had already implemented one as a matter of routine.

It's a little more complicated than that, the classes involved have to
have special interfaces to tell setf/getf what to do, sort of a
compile time equivalent of __setattr__/__getattr__ if I remember right.
 
P

Paul Rubin

Let us note that it's not FSF that gives this stuff away for free -- or
if it is them proximally, it is not them ultimately -- ultimately it's
the engineers who did all that work that gave it away for free.

When I worked there, they paid me ;-)
 
P

Paul Rubin

Bill Atkins said:
You should be pragmatic about this - I have never used a CL
implementation that didn't do TCO optimization (indeed, are there
any?). Although the standard doesn't require it, I treat it as a de
facto requirement and don't worry too much about it.

I have to confess that most of the Lisp code I've written were on
simpler dialects that didn't have TCO. But I'm not sure if the CL
implementations I've used (KCL back in the day, and CLISP a little
bit) had it either.
 
J

Juan R.

Kay said:
You mean a universal language adapter? I guess this is always possible
using alpha conversion but I don't believe this leads to theoretical or
practical interesting solutions but is just a limit concept.

Not familiarized with you terminology. I think that i would call that a
universal language composer.

I mean if there exists some theoretical limitation to composionality of
two directly collapsing languages (G1, T1) and (G2, T2) via a
unambiguous modification (e.g. 'renaming') to a third one (G2', T2'),
unknown to me. I mean some theoretical limitation in the sense of known
theoretical limitations to proving theorems in closed formal systems.
After all proving a formal theorem is not very different from
enhacement of a language.
The practical problem with composing enhancements is that any two
extensions L1, L2 share a lot of rules and rely on their structure.
What if they don't just extend their host language L0 conservatively
but also redefine rules of L0? This is not just a theoretical problem
but it happens quite naturally if you want to adapt an extension
developed for Python 2.4 for working with Python 2.5. Here Python 2.5
is considered as just another particular extension. Obviously Py3K will
become an interesting testcase for all kinds of syntactical and
semantical transformations.

I would consider redefined-L0 to be L0'. I think that a concept of
namespaces could be also used for versioning-like conflicts:
L0v24:foo(), L0v25:foo(). The problem is that both versions may be
stored and managed during initial period of time. But in the long run
old libraries, extensions... would be updated to the new version.
 
T

Timofei Shatrov

Are you aware that strings can be interned in Python?
Furthermore, any string literal in the source that
is a syntactically valid identifier is automatically
interned, and you can intern any string explicitly
if you need. This gives you exactly the same
capabilities as symbols in Lisp.

Are you aware that you hardly know any Lisp yet make such bold and unfounded
claims? Unless interning a string somehow gives it a property list, slot value
and function value it doesn't give you the same capabilities.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,685
Members
48,796
Latest member
Greg L.

Latest Threads

Top