Live data from Hacker News

Lisp vs Python

amitp.blogspot.com

81–90 of 98 posts

Re: Lisp vs Python

#81

Earlier quoted context omitted.

Python doesn't mandate block structure and indentation in lines within brackets and parens. Ask yourself why is that and you'll have the reason why it makes sense in Lisp. I'm very familiar with Python and hack occasionally in Scheme. After a really short time, parens really are no problem. They are an asset. In big functions where indentation stops being obvious at a glance (and in smaller ones, what's the problem?)…

Python doesn't mandate block structure and indentation in lines within brackets and parens. Ask yourself why is that and you'll have the reason why it makes sense in Lisp. Because they screwed up? I think indentation like the following should be mandatory across multiple lines: fun_a(long_arg_a, long_arg_b, long_arg_c)

And does that remove the need for parentheses? ;)

Because actually, it gets more complicated than that. Sometimes it makes more sense to say:

  def open_window(x, y
                  width, height,
                  resizable=True,
                  caption="")
Without parens, is x, y a tuple or two separate arguments? And do I want to remember that?

Also, what's inside the parens could have been a generator expression, which could have been conceivably partitioned in more than one sensible way, and which could have subexpressions with parens or brackets itself.

Sounds contrived? I do it all the time and it often looks and reads just fine.

I'm not arguing against your indentation rule, which is the one I use, and not even against the proposal of making it mandatory (although I'm not sure that in the heat of refactoring I'd appreciate the unnecessary SyntaxErrors), but about the point that making it mandatory would make parens unnecessary.

Re: Lisp vs Python

#82
post #73

Earlier quoted context omitted.

Do you have any data(even if anecdotal) to back up your claim? My experience is that macros don't obfuscate code at all(unless misused, I'm talking about idiomatic use of course). If i have the code loaded i just type (documentation 'macro-or-function-name 'function) to get its docstring. Slime can also show me its documentation and its argument list. Not to mention that a good macro(like any other well written code)…

Here's an anecdote from the other day: http://news.ycombinator.com/item?id=2240461 On another note, why do you think lisp isn't more widely used?

Others already pointed out the AI winter. Reading about the history of lisp is very interesting, it almost feels like you are reading about a lost civilization, so ahead of its time. On the other hand, the AI winter is in the past, why isn't lisp used NOW? I think its getting better, the scheme people are working on sorting out their issues, and of course theres Racket, which is awesome. You have the clojure people attracting a lot of java and ruby developers(among others) to at least give lisp a chance. And even the Common Lisp world is on the rise. The biggest problem IMHO is that there are too many non lisp programmers with strong opinions on lisp that spread FUD, even though all their lisp experience can be summarized as "read a scheme tutorial, and wrote a recursive factorial function".

Re: Lisp vs Python

#83

Earlier quoted context omitted.

Ah, I see -- this is a really good point, thanks for bringing it up. You're right, one can not arbitrarily increase scope in Python. The most common way I've seen of demarcating this kind of structure is actually using a blank line. For example, the code would instead look more like: c = create_context() for foo in foos: do_something(foo, c) do_other_thing(foo, c) accumulate(foos, c) do_other_stuff One could also thr…

One could also throw the separate stuff into a new function. That's the elephant in the room in all of these "my language is more readable" discussions, isn't it?

To be fair, that's what Lisp's let is syntactic sugar for, too.

Re: Lisp vs Python

#85

Earlier quoted context omitted.

Python is explicit about scope by using the same indentation block. I can glance at python code and immediately tell what the scope is because it's in the same indentation block (removing for the moment things like the global keyword, which tend not to be a problem in practice).

This isn't true, consider: if 1 (I'm retarded and don't know how to do comments that have new lines in the, but hopefully you catch the drift. The 'print c' is at 0 indentation)

Add at least two spaces at the beginning of each line and it will be treated as a preformatted block.

What you try to do is not legal Python. The else clause can't go in the same line.

I get your point, though. Python's scope is not in terms of literally 'indentation' blocks. Scope units are: module toplevel, and (possibly nested) function and class definitions. To create a new scope you create a new function. This is what Lisp does too (you can define let as a macro over lambda).

I have oscillated between liking either way better and at present I find Python's sloppier way more practical.

Re: Lisp vs Python

#86

Earlier quoted context omitted.

Can you increase indentation arbitrarily, though? Like, say I want to initialize some data for a loop, that I wouldn't need later, could I: main_scope_stuff() c = create_context() for foo in foos: do_something(foo, c) do_other_thing(foo, c) accumulate(foos, c) more_main_scope_stuff() to emphasize that c was only important to the loop and the call to "accumulate"?

Yes: main_scope_stuff() with create_context() as c: for foo in foos: do_something(foo, c) do_other_thing(foo, c) accumulate(foos, c) more_main_scope_stuff() That signifies that "c" isn't supposed to be available after scope of the "with" statement. The variable will still be bound, but conceptually it's unavailable, since it's not supposed to be used. Also, the object in create_context() needs to support being called…

> The variable will still be bound, but conceptually it's unavailable, since it's not supposed to be used.

Which, in all fairness, is the same as saying that this does not indeed create a new scope. If you're going to rely on convention, you might as well dispense with the 'with' statement at all and use blank lines.

An explicit and safe (if not very elegant) way to put a variable out of scope is just deleting it after you're done with it:

   main_scope_stuff()
   if True:  # Let's say we _really_ want indentation here..
       c = create_context()
       for foo in foos:
           do_something(foo, c)
           do_other_thing(foo, c)
       accumulate(foos, c)
       del c
    # something_or_other(c)  
That said, if it got to the point of going to this trouble I'd just make a nested function instead.

Re: Lisp vs Python

#87

Earlier quoted context omitted.

I did try it, but not enough, I guess, to tell the beautiful core you talk about from the rest. So Haskell seemed to me full of elegant ideas, yet less elegant, as a whole, than Scheme.

Which Scheme are you talking about? I find the awful type system of base R6RS to be extremely inelegant. Contracts and strong typing make formal reasoning about programs far more powerful, hence more modern Scheme-style languages like Racket.

Good catch. I was talking about R5RS and earlier.

Re: Lisp vs Python

#88

Earlier quoted context omitted.

This isn't true, consider: if 1 (I'm retarded and don't know how to do comments that have new lines in the, but hopefully you catch the drift. The 'print c' is at 0 indentation)

Add at least two spaces at the beginning of each line and it will be treated as a preformatted block. What you try to do is not legal Python. The else clause can't go in the same line. I get your point, though. Python's scope is not in terms of literally 'indentation' blocks. Scope units are: module toplevel, and (possibly nested) function and class definitions. To create a new scope you create a new function. This i…

Fixed, thank you for the tip. Yeah the point I was showing was that the 'c' exists after the if or else, showing that scope is not bound to indentation level. On the subject of scope, this behavior has gotten me a few times (I find it unintuitive although I understand why it works this way):

  x = 2
  f = lambda : x
  print f()
  x = 3
  print f()

Re: Lisp vs Python

#89
post #73

Earlier quoted context omitted.

Do you have any data(even if anecdotal) to back up your claim? My experience is that macros don't obfuscate code at all(unless misused, I'm talking about idiomatic use of course). If i have the code loaded i just type (documentation 'macro-or-function-name 'function) to get its docstring. Slime can also show me its documentation and its argument list. Not to mention that a good macro(like any other well written code)…

Here's an anecdote from the other day: http://news.ycombinator.com/item?id=2240461 On another note, why do you think lisp isn't more widely used?

Well, that anecdote talks about some people _fearing_ powerful, expressive languages.

In a previous job I had workmates arguing for banning "nested" Python list comprehensions. And as an example of such horrible nesting he proposed something like:

  some_list = [some_function(blah)
               for blah in some_other_function()
               if some_condition(blah)]
What this says to me is that this guy didn't get list comprehensions at all and didn't want to. Sure enough, there's no nesting whatsoever going on here. He was just scared by non-C++-like syntax.

My point is: popularity, though desirable in itself, is a poor measure of anything else. Most people run away from good things for no valid reason.

(Not saying there are no valid reasons why Lisp is not more popular, only that none would really be needed. Obscurity is quite a stable default.)

Re: Lisp vs Python

#90
post #47
post #18

> Lisp seems to be optimized for writing code; Python seems to be optimized for reading it. Urgh... A hundred times no. I really do appreciate that the author seems to have given Lisp a try. But this is simply wrong. Why does Lisp provide macros? Because they make code easier to read. I say stop focusing on what language abstraction (f x) represents and focus on figuring out what the code is doing . Oh well, at least…

Why does Lisp provide macros? Because they make code easier to read. To the person writing the code, yes. To the next coder maintaining the code, not likely.

Look through some really old Lisp code sometime. SBCL is highly readable despite being: 1) 25 years old and touched by tons of different people since then; 2) a program that does some really complicated things in a pretty small space (~60 KLOC for the arch-independent portion).

When you see (def-ir1-transform ...) in the SBCL source, it's immediately obvious what is about to come along (at least if you know about compilers). Similarly old C code (eg: GCC) is completely incomprehensible in comparison.

Post reply on HN