Python is Considered Harmful

Discussion in 'Python' started by mike420, Oct 27, 2003.

  1. mike420

    mike420 Guest

    Ladies and Gentlemen,

    I present to you the final and ultimate proof of Python's
    brain-damage:

    As you may remember,

    flist = []

    for i in range(3)
    f = lambda x: x + i
    flist.append(f)

    [f(1) for f in flist]

    produces [3, 3, 3] in Python.

    In Haskell, we would express this as follows:

    map (\f -> f 1) [\x -> x + i | i <- [0..2]]

    This, of course, evaluates to the expected [1, 2, 3]

    As you might have heard, the ever so generous GvR allowed us write
    the same in Python (literal translation, really):

    map(lambda f: f(1), [lambda x: x + 1 for i in range(3)])

    What do you think this evaluates to: also [1, 2, 3] or [3, 3, 3]
    as before?

    Guess again, it's [2, 2, 2] !

    ROTFLMFAO!

    Pythonista, you are all very welcome to learn Haskell.
    You will find the syntax very familiar. Haskell is short
    too (compare one line above that gives the correct
    result to several Python lines that surprise you)

    All this Python bashing is starting to feel like mocking
    a retarded child...

    420
     
    mike420, Oct 27, 2003
    #1
    1. Advertisements

  2. mike420

    Darius Guest

    Ladies and Gentlemen,

    I present to you the final and ultimate proof of mike420's
    brain-damage:

    In Haskell, we would express this as follows:

    map (\f -> f 1) [\x -> x + 1 | i <- [0..2]]

    This, of course, evaluates to the expected [2, 2, 2]

    map(lambda f: f(1), [lambda x: x + 1 for i in range(3)])

    What do you think this evaluates to: also [1, 2, 3] or [3, 3, 3]
    as before?

    It's [2, 2, 2] !

    -

    You are a blatant troll and now a public moron to boot. Will you please
    go away? You may consider coming back when you learn 1+1=2.
     
    Darius, Oct 27, 2003
    #2
    1. Advertisements

  3. mike420

    Ville Vainio Guest

    -1, Troll.
    Yes, 1+1 == 2 for usual values of 1.
    Well, the Haskell community seems like a friendly bunch, at least.
     
    Ville Vainio, Oct 27, 2003
    #3
  4. mike420

    Isaac To Guest

    mike420> As you might have heard, the ever so generous GvR allowed us
    mike420> write the same in Python (literal translation, really):

    mike420> map(lambda f: f(1), [lambda x: x + 1 for i in range(3)])

    mike420> What do you think this evaluates to: also [1, 2, 3] or [3, 3,
    mike420> 3] as before?

    mike420> Guess again, it's [2, 2, 2] !

    Did you really mean

    map(lambda f: f(1), [lambda x: x+i for i in range(3)])

    ? If so, it does return [3, 3, 3]. The only problem here is that Python
    variables are name lookups over dictionaries, and as such the value of "i"
    is not coined into the lambda. Rather it is "external", binded dynamically.
    I believe the behaviour can be fixed rather easily by some directives, say
    making it

    map(lambda f: f(1), [lambda x: x+(*i) for i in range(3)])

    where the * construct would get the reference of i at function definition
    time rather than at function invocation time (anyone can point me to an
    PEP?). On the other hand, I basically never use lambda this way.

    mike420> Pythonista, you are all very welcome to learn Haskell. You
    mike420> will find the syntax very familiar. Haskell is short too
    mike420> (compare one line above that gives the correct result to
    mike420> several Python lines that surprise you)

    Yes, tried. Failed, unluckily. It is clear that I'm not the kind of people
    who will map every programming problem into a mathematical problem and solve
    it that way. So I hate maps and reduces. I hate that I cannot assign a new
    value to an existing value to change its binding. I hate having to remember
    the unintuitive meanings of all the symbols. I hate having to guess when
    variables will get its bindings and when functions will be invoked during
    lazy evaluation. There is no way that anyone can turn me to Haskell.
    Basically every strong point Haskellers talk about turn me off. This is
    very unlucky.

    Regards,
    Isaac.
     
    Isaac To, Oct 27, 2003
    #4
  5. mike420

    KefX Guest

    Hmm...I think the Haskell syntax looks like crap. ;) Seriously, I can't even
    guess how it works without some kind of manual. And of course the Python result
    is only 'surprising' if you don't know the rules of name binding.

    I'm not bashing Haskell, of course. I'm just saying I already don't like it...

    - Kef
     
    KefX, Oct 27, 2003
    #5
  6. Perhaps that should read
     
    Martin Franklin, Oct 27, 2003
    #6
  7. Isaac To wrote:
    ...
    No new "directive" needed: it's easy to get "snap-shots" of current
    values of names into a lambda or other function:

    map(lambda f: f(1), [lambda x, i=i: x+i for i in range(3)])

    The "i=i" gets the (outer) value of i at function-definition time and
    injects it as local variable i in the lambda. You can also rename just
    as easily (and sometimes it's clearer):

    map(lambda f: f(1), [lambda x, k=i: x+k for i in range(3)])



    Alex
     
    Alex Martelli, Oct 27, 2003
    #7
  8. You're right, he's a troll. As a user of Haskell, I think such postings
    do an inexcusable amount of damage. Please ignore him, and don't
    judge the Haskell community by people like him.

    - Dirk

    [F'up to poster]
     
    Dirk Thierbach, Oct 27, 2003
    #8
  9. First, let's remove the list comprehension syntactical sugar. This is
    actually:

    map (\f -> f 1) (map (\i -> (\x -> x + i)) [0..2])

    So, as you can see clearly without the sugar, you're basically
    creating closures, since a new lexical scope is introduced at function
    creation.
    Expected by functional programmers who expect new lexical scopes to be
    created at every block, sure. But Python isn't a functional
    programming language, and doesn't create a new lexical scope in every
    block.
    Others have pointed out your typo here; I'll assume you meant "lambda
    x: x + i" instead of 1.

    Again, let's remove the syntactical sugar here:

    L = []
    for i in range(3):
    L.append(lambda x: x + i)
    map(lambda f: f(1), L)

    The observed result, [3, 3, 3] is perfectly in keeping with the fact
    that Python does not create a new lexical scope in for suites (or if
    suites, or any other non-class, non-function suite).
    The Python result is only surprising to those who try to impose other
    languages' semantics on Python.
    You, sir, are a poor representative of the Haskell community.

    Jeremy
     
    Jeremy Fincher, Oct 27, 2003
    #9
  10. [text snipped]
    Trolls are not welcomed, get lost.

    G. Rodrigues
     
    Gonçalo Rodrigues, Oct 27, 2003
    #10
  11. Well then, AFAIU, the

    lambda x, k = 1: ...

    idiom serves to introduce an optional lambda bound variable.
    I.e. something that in CL has been there since 1984 and earlier. Your
    suggestion is instead along the lines of the &AUX lambda parameter
    already present in Common Lisp (another non surprise) since 1984 and before.

    But this begs the question. The bottom line is that Python needs to get
    proper lambda expressions. The extra "quote" local "unquote" argument
    is not what you'd expect.

    Cheers
     
    Marco Antoniotti, Oct 27, 2003
    #11
  12. Unfortunately, Guido (van Rossum) has many times over voiced his
    non-support for functional constructs in Python.
    In other words, I guess he'd rather pull lambdas from Python than add
    "proper" support for them.

    And again, how do you define "proper"?

    Mauro
     
    Mauro Cicognini, Oct 27, 2003
    #12
  13. Thank you, Alex, for clarifing this issue for me..

    So this was actually like the famous equation
    "9*6=42"
    :)
    It is correct (or incorrect) if you look at it in the right (or wrong) way.

    Best,
    Miklós

    --
    PRISZNYÁK Miklós
    ---
    Jegenye 2001 Bt. ( mailto: )
    Egyedi szoftverkészítés, tanácsadás
    Custom software development, consulting
    http://jegenye2001.parkhosting.com


     
    Jegenye 2001 Bt, Oct 27, 2003
    #13
  14. mike420

    KefX Guest

    Nope, it's flat out wrong. The idea that it was true in a different base didn't
    even occur to Douglas Adams, if that's what you're suggesting. :) However, the
    analogy still works if you just pretend otherwise.

    - Kef
     
    KefX, Oct 27, 2003
    #14
  15. Yes, that's true but functional programmers come from a "carry your semantics
    on your sleave" angle at things. Let's see how we build this in Scheme. If I
    understand Python's semantics properly, a for-iterator has this semantics:

    (define-syntax python-for
    (syntax-rules (in range)
    [(_ x in (range n) exp ...)
    (let ([x #f])
    (for-each (lambda (i) (set! x i) exp ...) (build-list n identity)))]))

    It sets up an iteration variable and then mutates the iteration variable for
    each iteration. Then you evaluate the body of the for. A Schemer wouldn't cut
    the overhead and write/expect something like that:

    (define-syntax scheme-for
    (syntax-rules (in range)
    [(_ x in (range n) exp ...)
    (for-each (lambda (x) exp ...) (build-list n identity))]))

    Here we just iterate over the specified variable. (I have the iteration order of
    the number sequence backwards. That's intended to skip a small bit of syntactic
    overhead.)

    Now depending on which of these for's you use you get different results for

    (define flist '())

    (define f #f)

    (for i in (range 3)
    (set! f (lambda (x) (+ x i)))
    (set! flist (cons f flist)))

    (map (lambda (f) (f 1)) flist)

    Nothing surprising here for someone who studies language semantics. Things are
    as they are. But to someone who compares these things, I must admit that I am
    astonished that Python chose the first, complicated (not on your sleave)
    semantics and rejected the second one.

    -- Matthias
     
    Matthias Felleisen, Oct 28, 2003
    #15
  16. Nope, the left part of the equation is yet to be defined.
     
    Christos TZOTZIOY Georgiou, Oct 28, 2003
    #16
  17. Do you mean, implicitly using base 13? I know of no programming
    language that lets you set the number base to be used for literals
    (except presumably ones with particularly 'powerful' macros...?-)
    and I hope I never have to contend with one.


    Alex
     
    Alex Martelli, Oct 28, 2003
    #17
  18. You might be lucky :).

    /Justin
    --
     
    Justin Pearson, Oct 28, 2003
    #18
  19. Lisp, through the variable *read-base*. It's handy if you already
    have data (e.g., in a file generated by someone else) in a non-10
    base.

    Regards,
    Heather
     
    Heather Coppersmith, Oct 28, 2003
    #19
  20. Actually, I did work in Forth (it was the in-ROM language of a
    neat computer I once bought, called "Jupiter ACE"; and also of a
    special-purpose image processing PC card I once used at work),
    but never came across that "feature" (assuming those dialects of
    Forth in those ROMs supported it, that is). Guess I was lucky
    that in those special cases I wasn't sharing code w/others:).


    Alex
     
    Alex Martelli, Oct 28, 2003
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.