Live data from Hacker News

Lisp vs Python

amitp.blogspot.com

61–70 of 98 posts

Re: Lisp vs Python

#61

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"?

Of course it's possible to increase indentation arbitrarily: simply create a new function. Any programmer should know that too many immediate levels of lexical context is bound to confuse the reader anyway. I'm not really sure what you're trying to show with that code, though. Is your objection that every do_ function is requiring a context? Edit: I see what the parent was saying now, see bottom comment. Also, see St…

I want to communicate, using indentation, that more_main_scope_stuff() and subsequent code do not depend on c. c is conceptually part of the loop, and not of the surrounding code. (Like the initialization statement in C/C++).

The code I wrote does this (because c is 1 indentation level deeper than the main_scope functions). I do not know if it is legal Python to simply increase indentation level to demarcate a new scope, but I suspect it is not, and it is certainly not common practice.

This is really a minor gripe - but then again so are the article's - it's pretty easy to tell a binding from a function call.

Re: Lisp vs Python

#62

It's easy to read. You can determine how to interpret something—a string, a list, a function call, a definition—just by looking at the code locally. I actually find that Lisp scores some local-readability points over Python in a few cases, mainly because Lisp is more explicit about scope, e.g. (let ((a (something)) (b (other-thing)) (frobnicate a b)) ...other code versus a = something() b = other_thing() frobnicate(a…

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).

[deleted]

Re: Lisp vs Python

#63
post #38

Earlier quoted context omitted.

Beauty is subjective; elegance less so. Python is the language I've used and use the most, and I'll easily concede that Scheme is more elegant than almost anything else I've seen, and Python hardly even compares. Metaclasses, decorators, 'for'/'while'/'with' statements, etc. etc. In Python they are all good, practical, powerful ideas. In Scheme they're just unnecessary. Scheme is more elegant because it's been a prio…

Try Haskell. It has a strange mix of beautiful elegant core, and lots of (useful) syntactic sugar added on top.

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.

Re: Lisp vs Python

#64

Earlier quoted context omitted.

Python would argue that if the primary operating factor in readability is block structure and indentation one should simply add block structure and indentation as a mandatory part of the language and then remove cruft which is no longer necessary.

I'm not convinced that block structure and indentation are primary readability factors, just noting that Lisp programmers established conventions to address that problem long ago.

That's fair. I'm not saying Python's way is better or Lisp's way is better. I'm a long-time Python programmer but I'm also working on the Racket code base. I was simply pointing out a difference in philosophy, not taking sides. I mostly believe that the debate is a minor stylistic one and there are trade-offs in both directions. This is fundamentally similar to the way I see arguments for and against Python syntactical whitespace vs. Ruby-esque blocks.

Re: Lisp vs Python

#65
post #43

Earlier quoted context omitted.

>I'm not sure what massive win for macros is left. From my point of view, not being able to define new syntax is as serious a limitation as not being able to define new functions, or data structures. There are a number of specific examples usually cited to explain why the ability to define new syntax is important. Answering these specific examples by adding more static syntax to the language seems to be severely miss…

From my point of view, not being able to define new syntax is as serious a limitation as not being able to define new functions, or data structures. There's a pretty big difference. Both are about DRY. But functions are about abstracting functionality. Macros are about abstracting syntax. Both are useful and can reduce repitition, but in the general dev community, I don't think its clear that everyone is bought into…

> [...] in the general dev community, I don't think its clear that everyone is > bought into abstracting syntax too much. [...]

This seems like you're saying "python is better because it does the things people like and doesn't do the things they don't like". But the same argument could be used to claim Microsoft Windows is a great operating system, and that Justin Bieber is a great musician.

> Lisp [...] has never caught on in a big way [...]

This is factually incorrect. Scaled for the size of the industry, it was at one time as popular as Java was a few years ago. What happened then is well documented elsewhere. Search for "ai winter" and "worse is better" to start.

Re: Lisp vs Python

#66

Earlier quoted context omitted.

Of course it's possible to increase indentation arbitrarily: simply create a new function. Any programmer should know that too many immediate levels of lexical context is bound to confuse the reader anyway. I'm not really sure what you're trying to show with that code, though. Is your objection that every do_ function is requiring a context? Edit: I see what the parent was saying now, see bottom comment. Also, see St…

I want to communicate, using indentation, that more_main_scope_stuff() and subsequent code do not depend on c. c is conceptually part of the loop, and not of the surrounding code. (Like the initialization statement in C/C++). The code I wrote does this (because c is 1 indentation level deeper than the main_scope functions). I do not know if it is legal Python to simply increase indentation level to demarcate a new sc…

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 throw the separate stuff into a new function.

Re: Lisp vs Python

#67

Earlier quoted context omitted.

Python would argue that if the primary operating factor in readability is block structure and indentation one should simply add block structure and indentation as a mandatory part of the language and then remove cruft which is no longer necessary.

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)

Re: Lisp vs Python

#68
post #38

Earlier quoted context omitted.

Try Haskell. It has a strange mix of beautiful elegant core, and lots of (useful) syntactic sugar added on top.

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.

Re: Lisp vs Python

#69

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).

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 like that (i.e. it should contain __enter__ and __exit__ methods).

Re: Lisp vs Python

#70

Earlier quoted context omitted.

I want to communicate, using indentation, that more_main_scope_stuff() and subsequent code do not depend on c. c is conceptually part of the loop, and not of the surrounding code. (Like the initialization statement in C/C++). The code I wrote does this (because c is 1 indentation level deeper than the main_scope functions). I do not know if it is legal Python to simply increase indentation level to demarcate a new sc…

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?

Post reply on HN