Live data from Hacker News

Lisp vs Python

amitp.blogspot.com

31–40 of 98 posts

Re: Lisp vs Python

#31
post #15

>Python on the other hand has no macros I challenge this. I won't pretend that Python has full macro equivalence, but decorators are damned close.

Decorators are ways to wrap function definitions with code that gets executed at the time the function is defined. Commonly they add stuff that happens every time the function is called. This is certainly something you can do with macros, but it's not even really close to the full semantics. Macros allow you to add new special forms to the language. If Python had macros, for example, the new `with` statements would h…

Definitely.

Indeed decorators are a patch to a shortcoming in Python's ability to define anonymous functions or classes. If you could just say something like:

  f = memoized(lambda x, y:
                 ... some multiline function)
or

  C = coords_or_vectors(class:
                         ... some class definition)
you wouldn't need the kludge:

  @memoized
  def f(x, y):
      ...

  @coords_or_vectors
  class C:
      ...
Note that I'm not arguing for the syntax in the first two examples, just the ability to do the equivalent without special cases in the normal syntax of the language.

In Scheme you wouldn't need to learn the extra syntax, learn and remember the order in which decorators apply (top to bottom?, inner to outer?).

I was actually very happy when decorators got added to Python. But let's face it, they just give you a way out of a corner Python painted itself into. They're nothing to be too proud of.

Re: Lisp vs Python

#32
post #21

Earlier quoted context omitted.

No, I'm arguing against the ad hominem that forms the second half of your original post. The first half of your post was great. It addresses the arguments directly, and I completely agree. In the second half, you then go on to make assumptions about the programmer's experience and aptitude - assumptions that I've shown are quite false. If you want to debate the merits of an argument, debate the merits of an argument,…

[deleted]

[deleted]

Re: Lisp vs Python

#33

Earlier quoted context omitted.

No, I'm arguing against the ad hominem that forms the second half of your original post. The first half of your post was great. It addresses the arguments directly, and I completely agree. In the second half, you then go on to make assumptions about the programmer's experience and aptitude - assumptions that I've shown are quite false. If you want to debate the merits of an argument, debate the merits of an argument,…

"Why did s/he have to write it like that? It's cost us untold thousands of hours in coding around their nasty hacks and poor design decisions." However, I recognize the context they were operating in: they were a tiny startup of about 20 people, trying to organize the world's information. Yes, but if you're lucky enough to be Google Employee #7, you should now have time to do things like actually do your homework bef…

I've already said I agree with your basic thesis, but here's the tradeoff. Let's leave special forms out of this, on the assumption that any decent Lisp programmer will have them memorized, much like language keywords in other languages.

Say that you create a naming scheme for macros - maybe you require that every macro start with "macro-", or you require that they start with "def" and "with-", or whatever. You've now pretty much completely solved the problem Amit points out, that you can't tell whether any given expression will be evaluated or how many times.

But you've introduced another tradeoff: verbosity. If you prefix every form with macro-, your code looks a lot like C or JavaScript code that tries to use name prefixes to simulate namespaces, or (shudder) Java code with its AbstractFooBeanBuilderFactoryFactories. And if you use more natural prefixes like def or with-, you limit the flexibility of your macros. Where would aif from On Lisp fit in here?

In fact, if you're willing to prefix your names with a unique prefix, you can trivially build a macro system in Python. Here it is:

  gensym_counter = 0
  def gensym():
    gensym_counter += 1
    return "__gensym%d" % gensym_counter

  def macro-aif(cond, body):
    return macroexpand("""
      %(gensym)s = %(cond)s
      if %(gensym)s:
        it = $(gensym)s
        %(body)s
    """ % { 'gensym': gensym(), 'cond': cond, 'body': body)

  def macroexpand(program):
    def execute_macro(match):
      try:
        return globals()[match.group(1)](*match.groups()[1:])
      except KeyError:
        return match.group(0)
    return re.sub('(macro-\w+)\((?:(.+?)(?:,\s+|\))\)', execute_macro, program)
This doesn't handle the case where macro arguments might themselves contain commas, but that can be done through invoking the Python parser (which is included in the standard library) instead of doing a regexp substitution.

Re: Lisp vs Python

#34

Earlier quoted context omitted.

No, I'm arguing against the ad hominem that forms the second half of your original post. The first half of your post was great. It addresses the arguments directly, and I completely agree. In the second half, you then go on to make assumptions about the programmer's experience and aptitude - assumptions that I've shown are quite false. If you want to debate the merits of an argument, debate the merits of an argument,…

Ad hominem is disqualifying an argument based on attacks to the one making it. The comment you refer to is drawing (perhaps wrong) conclusions about the author of the OP from what he says. Warranted or not, it's not fallacious.

[deleted]

Re: Lisp vs Python

#35
post #34

Earlier quoted context omitted.

Ad hominem is disqualifying an argument based on attacks to the one making it. The comment you refer to is drawing (perhaps wrong) conclusions about the author of the OP from what he says. Warranted or not, it's not fallacious.

[deleted]

Actually, you should re-read the "why articles like this are incorrect" part. There's nothing essential to the argument that depends on the expertise of the author. Primarily, it's a description of articles of this type, and the particular things they lack.

Which, in addition to drawing incorrect conclusions and ad hominem, is also circular reasoning. Triple fallacy.

Nice try, it sounded good, but you're just blowing smoke here in defense of your friend.

Re: Lisp vs Python

#36
post #15

>Python on the other hand has no macros I challenge this. I won't pretend that Python has full macro equivalence, but decorators are damned close.

Decorators are ways to wrap function definitions with code that gets executed at the time the function is defined. Commonly they add stuff that happens every time the function is called. This is certainly something you can do with macros, but it's not even really close to the full semantics. Macros allow you to add new special forms to the language. If Python had macros, for example, the new `with` statements would h…

"Damned close" perhaps should be qualified as from the point of view of a Pythonista, given the ideals of that approach to programming. I took issue with the specific point that Python "has no macros", and then I qualified it, knowing full well that Lisp macros do more.

Decorators ultimately result in a function that is a substitute for another function. That function can have all sorts of wonderful runtime behavior, including access to arguments, the call stack, and other functions. Dismissing them as "adding stuff that happens every time the function is called" misses an entire dimension of their utility.

Re: Lisp vs Python

#37

>Python on the other hand has no macros I challenge this. I won't pretend that Python has full macro equivalence, but decorators are damned close.

Can you expand on this. What is something that macros can do that decorators can't? And likewise, what are some common uses of macros that decorators can do?

As jfm3 points out, you're not going to define new language syntax with decorators. You're also not going to apply them on the spot, inline with other code, since they are defined on a function, and aren't used in the same way as macros are in Lisp.

What you can do though is define behavior that varies based on the context. For example in Python you don't have function overloading or types, but with a decorator you can effectively create that type of behavior. So while you're not changing the language, you are changing the semantics of the functions you decorate.

Re: Lisp vs Python

#38
post #11

This is similar to the way I compare Python and Lisp: Common ground: first class functions, a lot of flexibility, closures Lisp: macros, performance? Python: easy to learn by example, readability, batteries included I use Python day-to-day as I don't really need a macro system that much. I also disagree that Lisp is more elegant - beauty is in the eye of the observer. Edit: formatting.

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.

Re: Lisp vs Python

#39
post #14

"Sometimes (f x) is [one of 6 things]" I don't mean to be the next snarky Lisp guy in the room, but I don't see the difference between reading (if (= a 3) ...) and thinking "that's a special form and a predicate", and reading if a == 3: ... and thinking "that's a special form and a predicate". In either case there's "if". Writing "(f x) could be anything" is a straw man. As soon as you replace "f" with "if" the argum…

Ah, but you can in Scheme. :)

    guile> (define if (lambda (. args) (display "Haha!") (newline)))
    guile> (if (= 3 4) 't 'f)
    Haha!

Re: Lisp vs Python

#40
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, b)
    ...other code
is more explicit about the intended lifetimes and consumers of the data "a" and "b". Lisp also has the "with a = (blah)" keyword for "loop" so the assignment can be made specifically in the context of loop preparation.

All in all I'm actually happier with my ability to signal my intent (and gauge other programmers' intent) in Lisp than I am in Python.

Post reply on HN