Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #6711 > unrolled thread
| Started by | harrismh777 <harrismh777@charter.net> |
|---|---|
| First post | 2011-05-31 01:48 -0500 |
| Last post | 2011-06-01 08:40 +1000 |
| Articles | 20 on this page of 47 — 13 participants |
Back to article view | Back to comp.lang.python
Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-05-31 01:48 -0500
Re: Something is rotten in Denmark... Chris Rebert <clp2@rebertia.com> - 2011-05-31 00:00 -0700
Re: Something is rotten in Denmark... Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-31 01:35 -0600
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-05-31 13:08 +0300
Re: Something is rotten in Denmark... Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-05-31 12:48 +0200
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-05-31 15:15 +0300
Re: Something is rotten in Denmark... Terry Reedy <tjreedy@udel.edu> - 2011-05-31 13:11 -0400
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-05-31 15:18 -0500
Re: Something is rotten in Denmark... Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-31 16:24 -0600
Re: Something is rotten in Denmark... Terry Reedy <tjreedy@udel.edu> - 2011-05-31 19:14 -0400
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-05-31 19:09 -0500
Re: Something is rotten in Denmark... Terry Reedy <tjreedy@udel.edu> - 2011-06-01 13:11 -0400
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-06-01 19:40 -0500
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-06-01 19:50 -0500
Re: Something is rotten in Denmark... Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-02 04:37 +0000
Re: Something is rotten in Denmark... Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-02 05:14 +0000
Re: Something is rotten in Denmark... Chris Angelico <rosuav@gmail.com> - 2011-06-02 18:02 +1000
Re: Something is rotten in Denmark... Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2011-06-02 13:00 +0200
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-06-02 15:51 +0300
Re: Something is rotten in Denmark... Terry Reedy <tjreedy@udel.edu> - 2011-06-02 15:43 -0400
Re: Something is rotten in Denmark... Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-06-03 11:43 +1200
Re: Something is rotten in Denmark... rusi <rustompmody@gmail.com> - 2011-06-02 19:24 -0700
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-06-03 09:17 +0300
Re: Something is rotten in Denmark... rusi <rustompmody@gmail.com> - 2011-06-05 03:54 -0700
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-06-05 15:03 +0300
Re: Something is rotten in Denmark... rusi <rustompmody@gmail.com> - 2011-06-05 05:26 -0700
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-06-05 16:10 +0300
Re: Something is rotten in Denmark... Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-06-03 10:30 +0200
Re: Something is rotten in Denmark... Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-03 11:53 -0600
Re: Something is rotten in Denmark... Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2011-06-03 12:35 +0200
Re: Something is rotten in Denmark... Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2011-06-03 14:07 +0300
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-06-03 15:38 -0500
Re: Something is rotten in Denmark... Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-06-04 12:40 +1200
Re: Something is rotten in Denmark... Nobody <nobody@nowhere.com> - 2011-06-03 14:07 +0100
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-06-02 10:44 -0500
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-06-02 10:55 -0500
Re: Something is rotten in Denmark... Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-02 17:22 +0000
Re: Something is rotten in Denmark... Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-02 11:43 -0600
Re: Something is rotten in Denmark... Terry Reedy <tjreedy@udel.edu> - 2011-06-02 02:02 -0400
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-06-02 11:02 -0500
Re: Something is rotten in Denmark... Martin Manns <mmanns@gmx.net> - 2011-05-31 23:14 +0200
Re: Something is rotten in Denmark... Ian Kelly <ian.g.kelly@gmail.com> - 2011-05-31 15:47 -0600
Re: Something is rotten in Denmark... Martin Manns <mmanns@gmx.net> - 2011-06-01 02:57 +0200
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-05-31 16:53 -0500
Re: Something is rotten in Denmark... harrismh777 <harrismh777@charter.net> - 2011-05-31 17:06 -0500
Re: Something is rotten in Denmark... Chris Angelico <rosuav@gmail.com> - 2011-06-01 08:39 +1000
Re: Something is rotten in Denmark... Chris Angelico <rosuav@gmail.com> - 2011-06-01 08:40 +1000
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2011-06-03 11:43 +1200 |
| Message-ID | <94qlhsFkriU1@mid.individual.net> |
| In reply to | #6854 |
Alain Ketterlin wrote: > But going against generally accepted semantics should at least > be clearly indicated. Lambda is one of the oldest computing abstraction, > and they are at the core of any functional programming language. Yes, and Python's lambdas behave exactly the *same* way as every other language's lambdas in this area. Changing it to do early binding would be "going against generally accepted semantics". It's not the lambda that's different from other languages, it's the for-loop. In languages that encourage a functional style of programming, the moral equivalent of a for-loop is usually some construct that results in a new binding of the control variable each time round, so the problem doesn't arise very often. If anything should be changed here, it's the for-loop, not lambda. -- Greg
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2011-06-02 19:24 -0700 |
| Message-ID | <238bf9b2-fa07-4da3-b7a0-3bf07a6bd947@q12g2000prb.googlegroups.com> |
| In reply to | #6898 |
On Jun 3, 4:43 am, Gregory Ewing <greg.ew...@canterbury.ac.nz> wrote:
> Alain Ketterlin wrote:
> > But going against generally accepted semantics should at least
> > be clearly indicated. Lambda is one of the oldest computing abstraction,
> > and they are at the core of any functional programming language.
>
> Yes, and Python's lambdas behave exactly the *same* way as
> every other language's lambdas in this area. Changing it to
> do early binding would be "going against generally accepted
> semantics".
>
> It's not the lambda that's different from other languages,
> it's the for-loop. In languages that encourage a functional
> style of programming, the moral equivalent of a for-loop is
> usually some construct that results in a new binding of the
> control variable each time round, so the problem doesn't
> arise very often.
>
> If anything should be changed here, it's the for-loop, not
> lambda.
>
> --
> Greg
I also thought so
So I tried:
Recast the comprehension as a map
Rewrite the map into a fmap (functionalmap) to create new bindings
def fmap(f,lst):
if not lst: return []
return [f(lst[0])] + fmap(f, lst[1:])
Still the same effects.
Obviously I am changing it at the wrong place...
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2011-06-03 09:17 +0300 |
| Message-ID | <qotd3ivtp5k.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #6903 |
rusi writes: > So I tried: > Recast the comprehension as a map > Rewrite the map into a fmap (functionalmap) to create new bindings > > def fmap(f,lst): > if not lst: return [] > return [f(lst[0])] + fmap(f, lst[1:]) > > Still the same effects. > > Obviously I am changing it at the wrong place... >>> fs = [(lambda n : n + i) for i in range(10)] >>> [f(1) for f in fs] [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] >>> fs = list(map(lambda i : lambda n : n + i, range(10))) >>> list(map(lambda f : f(1), fs)) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2011-06-05 03:54 -0700 |
| Message-ID | <8b46f9a0-1b32-42cb-9f02-a520ae5ca787@r35g2000prj.googlegroups.com> |
| In reply to | #6916 |
On Jun 3, 11:17 am, Jussi Piitulainen <jpiit...@ling.helsinki.fi> wrote: > rusi writes: > > So I tried: > > Recast the comprehension as a map > > Rewrite the map into a fmap (functionalmap) to create new bindings > > > def fmap(f,lst): > > if not lst: return [] > > return [f(lst[0])] + fmap(f, lst[1:]) > > > Still the same effects. > > > Obviously I am changing it at the wrong place... > > >>> fs = [(lambda n : n + i) for i in range(10)] > >>> [f(1) for f in fs] > [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] > > >>> fs = list(map(lambda i : lambda n : n + i, range(10))) > >>> list(map(lambda f : f(1), fs)) > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Thanks Jussi for that code -- but I am not fully able to wrap my head around it. Is the problem in the lambda? ZF? Are you trying to say that map works (functionally) and ZF is imperative?
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2011-06-05 15:03 +0300 |
| Message-ID | <qotr578bi49.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #7042 |
rusi writes: > On Jun 3, 11:17 am, Jussi Piitulainen wrote: > > rusi writes: > > > So I tried: > > > Recast the comprehension as a map > > > Rewrite the map into a fmap (functionalmap) to create new bindings > > > > > def fmap(f,lst): > > > if not lst: return [] > > > return [f(lst[0])] + fmap(f, lst[1:]) > > > > > Still the same effects. > > > > > Obviously I am changing it at the wrong place... > > > > >>> fs = [(lambda n : n + i) for i in range(10)] > > >>> [f(1) for f in fs] > > [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] > > > > >>> fs = list(map(lambda i : lambda n : n + i, range(10))) > > >>> list(map(lambda f : f(1), fs)) > > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] > > Thanks Jussi for that code -- but I am not fully able to wrap my head > around it. Oops, sorry, I seem to have edited out a question that I meant to ask. The question was this: How do -you- write the list comprehension in terms of your fmap? What -is- the expression that still has the same effects? That is, where do you bind the i's? The obvious-to-me way is shown above, but there it is the outer lambda that establishes the distinct i's for the different closures. (The composition list(map(...)) works in both versions of Python.) > Is the problem in the lambda? ZF? > Are you trying to say that map works (functionally) and ZF is > imperative? Sorry, what is ZF? I'm saying that your fmap works, but in itself it does not provide the bindings that we are talking about, and you didn't show what does. The outer lambda in my example does that. The Python list comprehension [... for i in ...] binds (or assigns to) just one i which is shared by all the closures above. They end up having the same value for i because it's the same i. I hope this is less obscure now.
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2011-06-05 05:26 -0700 |
| Message-ID | <cec48785-d239-46d5-9a24-5a9c892bce77@y27g2000prb.googlegroups.com> |
| In reply to | #7044 |
On Jun 5, 5:03 pm, Jussi Piitulainen <jpiit...@ling.helsinki.fi> wrote: > rusi writes: > > On Jun 3, 11:17 am, Jussi Piitulainen wrote: > > > rusi writes: > > > > So I tried: > > > > Recast the comprehension as a map > > > > Rewrite the map into a fmap (functionalmap) to create new bindings > > > > > def fmap(f,lst): > > > > if not lst: return [] > > > > return [f(lst[0])] + fmap(f, lst[1:]) > > > > > Still the same effects. > > > > > Obviously I am changing it at the wrong place... > > > > >>> fs = [(lambda n : n + i) for i in range(10)] > > > >>> [f(1) for f in fs] > > > [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] > > > > >>> fs = list(map(lambda i : lambda n : n + i, range(10))) > > > >>> list(map(lambda f : f(1), fs)) > > > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] > > > Thanks Jussi for that code -- but I am not fully able to wrap my head > > around it. > > Oops, sorry, I seem to have edited out a question that I meant to ask. > The question was this: How do -you- write the list comprehension in > terms of your fmap? What -is- the expression that still has the same > effects? That is, where do you bind the i's? > > The obvious-to-me way is shown above, but there it is the outer lambda > that establishes the distinct i's for the different closures. > > (The composition list(map(...)) works in both versions of Python.) > > > Is the problem in the lambda? ZF? > > Are you trying to say that map works (functionally) and ZF is > > imperative? > > Sorry, what is ZF? > > I'm saying that your fmap works, but in itself it does not provide the > bindings that we are talking about, and you didn't show what does. The > outer lambda in my example does that. > > The Python list comprehension [... for i in ...] binds (or assigns to) > just one i which is shared by all the closures above. They end up > having the same value for i because it's the same i. > > I hope this is less obscure now. I was wondering why the list(... Now I see that map returns normal lists in python2 and some generator- like-thing in 3 I would have said: Shall we just stick to 2 (for this discussion) but then 2 seems to have a double error that self-corrects this example... OOOOFFF -- too many variables... [ZF is Zermelo-Fraenkel -- old name for list comprehension -- I guess my age leaks like python's ZF (sorry comprehension) :-) ] Anyway... My (summary,tentative) conclusion is that python's comprehensions leak. The one leak fixed in python3 has not fixed the other (revealed in this thread) All this has little to do with lambda (whose scope rules were fixed around python 2.2 IIRC) I'd be interested in ur take on this...
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2011-06-05 16:10 +0300 |
| Message-ID | <qotmxhw5sq2.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #7045 |
rusi writes: > On Jun 5, 5:03 pm, Jussi Piitulainen wrote: > > rusi writes: > > > On Jun 3, 11:17 am, Jussi Piitulainen wrote: > > > > rusi writes: > > > > > So I tried: > > > > > Recast the comprehension as a map > > > > > Rewrite the map into a fmap (functionalmap) to create new bindings > > > > > > > def fmap(f,lst): > > > > > if not lst: return [] > > > > > return [f(lst[0])] + fmap(f, lst[1:]) > > > > > > > Still the same effects. > > > > > > > Obviously I am changing it at the wrong place... > > > > > > >>> fs = [(lambda n : n + i) for i in range(10)] > > > > >>> [f(1) for f in fs] > > > > [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] > > > > > > >>> fs = list(map(lambda i : lambda n : n + i, range(10))) > > > > >>> list(map(lambda f : f(1), fs)) > > > > [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] > > > > > Thanks Jussi for that code -- but I am not fully able to wrap my head > > > around it. > > > > Oops, sorry, I seem to have edited out a question that I meant to ask. > > The question was this: How do -you- write the list comprehension in > > terms of your fmap? What -is- the expression that still has the same > > effects? That is, where do you bind the i's? > > > > The obvious-to-me way is shown above, but there it is the outer lambda > > that establishes the distinct i's for the different closures. > > > > (The composition list(map(...)) works in both versions of Python.) > > > > > Is the problem in the lambda? ZF? > > > Are you trying to say that map works (functionally) and ZF is > > > imperative? > > > > Sorry, what is ZF? > > > > I'm saying that your fmap works, but in itself it does not provide the > > bindings that we are talking about, and you didn't show what does. The > > outer lambda in my example does that. > > > > The Python list comprehension [... for i in ...] binds (or assigns to) > > just one i which is shared by all the closures above. They end up > > having the same value for i because it's the same i. > > > > I hope this is less obscure now. > > I was wondering why the list(... > Now I see that map returns normal lists in python2 and some generator- > like-thing in 3 > I would have said: Shall we just stick to 2 (for this discussion) but > then 2 seems to have a double error that self-corrects this example... > > OOOOFFF -- too many variables... > > [ZF is Zermelo-Fraenkel -- old name for list comprehension -- I guess > my age leaks like python's ZF (sorry comprehension) :-) ] Oh, ok. Zermelo-Fraenkel came to mind, but I didn't know it's been used as a name for list comprehensions. > Anyway... My (summary,tentative) conclusion is that python's > comprehensions leak. > The one leak fixed in python3 has not fixed the other (revealed in > this thread) > > All this has little to do with lambda (whose scope rules were fixed > around python 2.2 IIRC) > > I'd be interested in ur take on this... I think we agree. I've been saying all along that the perceived problem is not with the lambda at all but with the way the list comprehension deals with its variable. (I see that some people understand the situation correctly but blame the lambda anyway.) Personally, I like your summary, but I'm enough of an outsider that I do not want to suggest that there is anything wrong with Python. I just wish to understand how it works, as with any language that I use. The issue of this thread seems to turn up repeatedly, but is there a problem with the language mechanisms, is there a problem with the ways we talk about the language, or is this just the case where people need to be educated? I'm not sure. (Incidentally, I'm so new to Python that I started right with 3.0. I use some 2.4, 2.5-ish a little because software on a certain server is not kept updated, but I never knew 2.2.)
[toc] | [prev] | [next] | [standalone]
| From | Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> |
|---|---|
| Date | 2011-06-03 10:30 +0200 |
| Message-ID | <isa62l$5uu$1@r03.glglgl.eu> |
| In reply to | #6898 |
Am 03.06.2011 01:43 schrieb Gregory Ewing: > It's not the lambda that's different from other languages, > it's the for-loop. In languages that encourage a functional > style of programming, the moral equivalent of a for-loop is > usually some construct that results in a new binding of the > control variable each time round, so the problem doesn't > arise very often. > > If anything should be changed here, it's the for-loop, not > lambda. In my opinion, it is rather the closure thing which confused me at some time, and that's exactly what is the subject of the thread. On one hand, a closure can be quite handy because I have access to an "outer" vaiable even it changes. But on the other hand, I might want to have exactly the value the variable had when defining the function. So there should be a way to exactly do so: funcs=[] for i in range(100): def f(): return i funcs.append(f) for f in funcs: f() Here, i should not be transported as "look what value i will get", but "look what value i had when defining the function". So there should be a way to replace the closure of a function with a snapshot of it at a certain time. If there was an internal function with access to the readonly attribute func_closure and with the capability of changing or creating a cell object and thus hbeing capable of doing so, it could be used a a decorator for a function to be "closure-snapshotted". So in funcs=[] for i in range(100): @closure_snapshot def f(): return i funcs.append(f) each f's closure content cells would just be changed not to point to the given variables, but to a cell referenced nowhere else and initialized with the reference pointed to by the original cells at the given time. Thomas
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-06-03 11:53 -0600 |
| Message-ID | <mailman.2436.1307123618.9059.python-list@python.org> |
| In reply to | #6927 |
On Fri, Jun 3, 2011 at 2:30 AM, Thomas Rachel
<nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de>
wrote:
> So there should be a way to replace the closure of a function with a
> snapshot of it at a certain time. If there was an internal function with
> access to the readonly attribute func_closure and with the capability of
> changing or creating a cell object and thus hbeing capable of doing so, it
> could be used a a decorator for a function to be "closure-snapshotted".
>
> So in
>
> funcs=[]
> for i in range(100):
> @closure_snapshot
> def f(): return i
> funcs.append(f)
>
> each f's closure content cells would just be changed not to point to the
> given variables, but to a cell referenced nowhere else and initialized with
> the reference pointed to by the original cells at the given time.
For CPython 3.2:
import functools
import types
def makecell(value):
def f():
return value
return f.__closure__[0]
def closure_snapshot(f):
if f.__closure__:
snapshot = tuple(makecell(cell.cell_contents) for cell in f.__closure__)
else:
snapshot = f.__closure__
g = types.FunctionType(f.__code__, f.__globals__.copy(), f.__name__,
f.__defaults__, snapshot)
functools.update_wrapper(g, f, functools.WRAPPER_ASSIGNMENTS +
('__kwdefaults__',))
return g
>>> funcs = []
>>> for i in range(10):
... @closure_snapshot
... def f(): return i
... funcs.append(f)
...
>>> [f() for f in funcs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> funcs = [closure_snapshot(lambda: i) for i in range(10)]
>>> [f() for f in funcs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
It doesn't really seem any more straightforward to me than the "i=i"
trick. Also, I don't know how portable this is to different Python
implementations or future versions. Finally, note that in order to
make this work correctly in all cases (such as the first example
above, where i is a global, not a cell) we have to snapshot the
globals as well, which could cause further confusion.
Cheers,
Ian
[toc] | [prev] | [next] | [standalone]
| From | Alain Ketterlin <alain@dpt-info.u-strasbg.fr> |
|---|---|
| Date | 2011-06-03 12:35 +0200 |
| Message-ID | <87vcwnqk2j.fsf@dpt-info.u-strasbg.fr> |
| In reply to | #6898 |
Gregory Ewing <greg.ewing@canterbury.ac.nz> writes: > Alain Ketterlin wrote: >> But going against generally accepted semantics should at least >> be clearly indicated. Lambda is one of the oldest computing abstraction, >> and they are at the core of any functional programming language. > > Yes, and Python's lambdas behave exactly the *same* way as > every other language's lambdas in this area. Changing it to > do early binding would be "going against generally accepted > semantics". You must be kidding. Like many others, you seem to think that Scheme is a typical functional language, which it is not. Learn about ML (i.e., SML or CaML), Erlang, Haskell, etc. You can read, e.g., http://en.wikipedia.org/wiki/Closure_%28computer_science%29 The reason why we have the kind of lambdas we have in python (and scheme, and javascript, etc.) is just that it is way easier to implement. That's all I've said. And people have gotten used to it, without ever realizing they are using something completely different from what Church called the "lambda abstraction". Whether the python/... concept of lambda is useful or not is another, subjective question, that I'm not intersted in. If you're pleased with it, go ahead. (End of discussion for me.) -- Alain.
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2011-06-03 14:07 +0300 |
| Message-ID | <qot7h93qikx.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #6933 |
Alain Ketterlin writes: > Gregory Ewing writes: > > > Alain Ketterlin wrote: > >> But going against generally accepted semantics should at least be > >> clearly indicated. Lambda is one of the oldest computing > >> abstraction, and they are at the core of any functional > >> programming language. > > > > Yes, and Python's lambdas behave exactly the *same* way as every > > other language's lambdas in this area. Changing it to do early > > binding would be "going against generally accepted semantics". > > You must be kidding. Like many others, you seem to think that Scheme is > a typical functional language, which it is not. Learn about ML (i.e., > SML or CaML), Erlang, Haskell, etc. You can read, e.g., > http://en.wikipedia.org/wiki/Closure_%28computer_science%29 That seems a good read, but I don't see how it supports your contention that Python goes against generally accepted semantics. > The reason why we have the kind of lambdas we have in python (and > scheme, and javascript, etc.) is just that it is way easier to > implement. That's all I've said. And people have gotten used to it, > without ever realizing they are using something completely different > from what Church called the "lambda abstraction". Church did not deal with assignment statements and order of execution. Python has to. > Whether the python/... concept of lambda is useful or not is another, > subjective question, that I'm not intersted in. If you're pleased with > it, go ahead. > > (End of discussion for me.) Oh well.
[toc] | [prev] | [next] | [standalone]
| From | harrismh777 <harrismh777@charter.net> |
|---|---|
| Date | 2011-06-03 15:38 -0500 |
| Message-ID | <gDbGp.1$9l.0@newsfe08.iad> |
| In reply to | #6933 |
Alain Ketterlin wrote:
> The reason why we have the kind of lambdas we have in python (and
> scheme, and javascript, etc.) is just that it is way easier to
> implement. That's all I've said. And people have gotten used to it,
> without ever realizing they are using something completely different
> from what Church called the "lambda abstraction".
>
This is why I'm willing to accept Terry's 'hypnotized'
accreditation. The term 'lambda' carries some baggage with it that
python has chosen to ignore. Using the term 'lambda' as short-hand for
'an easier way to code in-line functions' causes some of the hypnotizing
effect, and much of the misunderstanding.
Frankly, having thought this over for several days, I am now
convinced the the issue at hand is two-fold: 1) the closure should
provide option(s) for snap-shot, and 2) the lambda should be implemented
in a 'purely' functional way or eliminated... if eliminated another
synonym could be invented to represent in-line function short-hand.
This is clearing up for me... but probably just beginning to simmer
for others.
kind regards,
m harris
[toc] | [prev] | [next] | [standalone]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2011-06-04 12:40 +1200 |
| Message-ID | <94td8nFdpkU1@mid.individual.net> |
| In reply to | #6933 |
Alain Ketterlin wrote: > You must be kidding. Like many others, you seem to think that Scheme is > a typical functional language, which it is not. I never said that Scheme is a functional language -- I'd be the first to acknowledge that it's not. I do know what real functional languages are like. However, Scheme is more relevant to this discussion than Haskell, precisely because it's *not* purely functional -- it does allow existing bindings to be changed. Yet its lambdas are late-binding, and nobody seems to get tripped up by that they way they do in Python. Why not? It's because Scheme encourages a style of programming which favours creation of new bindings rather than changing existing ones, so most of the time the bindings captured by a lambda don't change later. -- Greg
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2011-06-03 14:07 +0100 |
| Message-ID | <pan.2011.06.03.13.07.40.156000@nowhere.com> |
| In reply to | #6898 |
On Fri, 03 Jun 2011 11:43:54 +1200, Gregory Ewing wrote: >> But going against generally accepted semantics should at least >> be clearly indicated. Lambda is one of the oldest computing abstraction, >> and they are at the core of any functional programming language. > > Yes, and Python's lambdas behave exactly the *same* way as > every other language's lambdas in this area. Changing it to > do early binding would be "going against generally accepted > semantics". In Lisp, it depends upon whether the free variable is bound: $ clisp [1]> (setq f (lambda (x) (+ x i))) #<FUNCTION :LAMBDA (X) (+ X I)> [2]> (setq i 7) 7 [3]> (apply f (list 4)) 11 [4]> (setq i 12) 12 [5]> (apply f (list 4)) 16 ^D $ clisp [1]> (let ((i 7)) (setq f (lambda (x) (+ x i)))) #<FUNCTION :LAMBDA (X) (+ X I)> [2]> (apply f (list 4)) 11 [3]> (setq i 12) 12 [4]> (apply f (list 4)) 11 ^D If the variable is bound, then the lambda creates a closure. And Python behaves the same way: > f = (lambda i: lambda x: x + i)(7) > f(4) 11 > i = 12 > f(4) 11 # If you really want a "let", this syntax is closer: # f = (lambda i = 7: lambda x: x + i)() The original semantics (from the lambda calculus) don't deal with the concept of mutable state. > If anything should be changed here, it's the for-loop, not lambda. Right. The for loop should bind the variable rather than set it.
[toc] | [prev] | [next] | [standalone]
| From | harrismh777 <harrismh777@charter.net> |
|---|---|
| Date | 2011-06-02 10:44 -0500 |
| Message-ID | <5dOFp.25708$oq.13740@newsfe17.iad> |
| In reply to | #6839 |
Steven D'Aprano wrote:
> funcs = [(lambda x, i=j: x+i) for j in range(10)]
>
> Now the reader is no longer distracted by the "i=i" ugliness.
That's a good idea, in fact, change made!
> The problem with Do What I Mean is that it so rarely Does What You Mean.
> At best it Does What Some Other Guy Imagined I'd Probably Mean In This
> Situation. Let's not go there.
Oh, I agree. This is one of those things where I agree
(tongue-in-cheek) in all cases except the one I'm whining about! :)
--just kidding, here. Yes, ambiguous is bad.
[toc] | [prev] | [next] | [standalone]
| From | harrismh777 <harrismh777@charter.net> |
|---|---|
| Date | 2011-06-02 10:55 -0500 |
| Message-ID | <9oOFp.2056$Zp6.1700@newsfe19.iad> |
| In reply to | #6839 |
Steven D'Aprano wrote:
> What do you expect this code to do?
>
> a = 42
> funcs = [(lambda x: x+a) for i in range(10)]
> funcs[0](1)
I do see your point with this... truly... but it did get me to think
about what I *do* expect... and that is that 'a' (for the lambda) will
be whatever 'a' is (now) at the time when the anonymous function is
returned, not later when it is called (not really). If I understand
things correctly, if 'a' references a different simple int object
'later' (before the anonymous function is called) then the result of the
lambda may not be what was expected. In your example, of course, the 'i'
is not relevant. On the other hand, as in callbacks, the whole reason
we want to use the lambda in the first place is because we don't know
what the data will be 'later,' and in fact we really do want
'late-binding' after all. (I guess, I want my cake on a nice china
saucer, with a silver spoon, 'and' I want to eat it too... ) 'magine that!
I know, you're saying "well, duh". But here's the thing... that's
the beauty and the curse of pure functional programming (like haskell)
which (by the way) doesn't have this problem, because doesn't have
mutables as in Python ( nor other languages, non functional ). So, those
of us attempting to morph functional programming over python are having
a little difficulty because what we expect to happen with the lambda in
a list comprehension is adversely affected by our misunderstanding of
python's 'late-binding'. See the whine, here?
kind regards,
m harris
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-06-02 17:22 +0000 |
| Message-ID | <4de7c6e7$0$29996$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #6869 |
On Thu, 02 Jun 2011 10:55:49 -0500, harrismh777 wrote: > Steven D'Aprano wrote: >> What do you expect this code to do? >> >> a = 42 >> funcs = [(lambda x: x+a) for i in range(10)] funcs[0](1) > > I do see your point with this... truly... but it did get me to think > about what I *do* expect... and that is that 'a' (for the lambda) will > be whatever 'a' is (now) at the time when the anonymous function is > returned, not later when it is called (not really). Arguably, there's nothing wrong with early binding as a strategy. It's just a different strategy from late binding. It seems to me that early binding is less flexible than late, because with late binding you have a chance to simulate early binding by saving a reference of the variable elsewhere, such as in a default value, or an instance attribute. But with early binding, you're stuck. There's no simple or straightforward way to simulate late binding in an early binding language. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-06-02 11:43 -0600 |
| Message-ID | <mailman.2394.1307036619.9059.python-list@python.org> |
| In reply to | #6874 |
On Thu, Jun 2, 2011 at 11:22 AM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > It seems to me that early binding is less flexible than late, because > with late binding you have a chance to simulate early binding by saving a > reference of the variable elsewhere, such as in a default value, or an > instance attribute. But with early binding, you're stuck. There's no > simple or straightforward way to simulate late binding in an early > binding language. Well, you can always do something like this: >>> a = box(42) >>> func = lambda x: a.value + x >>> func(1) 43 >>> a.value = 6 * 9 >>> func(1) 55 I realize that's not exactly the same thing since you're stuck working with "a.value" instead of just "a", but it does produce the desired result. Cheers, Ian
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-06-02 02:02 -0400 |
| Message-ID | <mailman.2381.1306994558.9059.python-list@python.org> |
| In reply to | #6828 |
On 6/1/2011 8:40 PM, harrismh777 wrote: > The part that I don't see much about in the docs (some books, that is) > is that the lambda lookups occur late (the lambda is evaluated at the > time it is called). The Python docs on-line *do say* this (I found too > late) but its one quick phrase that can be missed. So, the i in > range(10) is sitting there at '9' by the time *any* of the ten lambdas > get called. This is not intuitive, nor good. IMHO I readily admit that the docs might be improved. Part of the reason I spend time responding to issues like this is to practive giving explanations that I might use in my own writings or even in the doc. I have at least one small idea already. > Yes, I can explicitly grab each 'i' as it flies by with a little clever > coding of the default value for the lambda n, i=i: i + n but that > 'trick' is not intuitive, nor is it clear reading. It 'works' is just > about all one can say for it (not very elegant). You found the alternative of using a closure (the g(i) that returns a *new* function for each i). You happened to use lambda to create each new function; a nested def statement would have served just as well. Replacing the default arg trick was one of the reasons to introduce closures (in about 2.3). It might be considered the recommended solution to this use case. > work. I'm wondering if whether it would make some sense to put some > 'binding smarts' into the interpreter to allow for 'interpreter > intuition' (say AI ) that would presume to understand when early vs late > binding makes sense and apply early binding in those cases where the > context is not ambiguous and when it is clear that an iterable is being > passed to the constant lambda function? Oh the irony of this proposal. You scolded us for breaking code with 2 to 3 changes, and here you propose a change more radical than anything done in Python 3, and certain to break code, introduce bugs, complicate the language, and reduce its functionality. Most of Guido's design decision are rejections of such changes ;-). -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | harrismh777 <harrismh777@charter.net> |
|---|---|
| Date | 2011-06-02 11:02 -0500 |
| Message-ID | <CuOFp.39468$Vp.19473@newsfe14.iad> |
| In reply to | #6841 |
Terry Reedy wrote:
> Oh the irony of this proposal. You scolded us for breaking code with 2
> to 3 changes, and here you propose a change more radical than anything
> done in Python 3, and certain to break code, introduce bugs, complicate
> the language, and reduce its functionality. Most of Guido's design
> decision are rejections of such changes ;-).
Yeah, I knew that was coming... and I deserved it too! :)
Yes, I'm torn a bit over this surprise. Because I really don't want
anything like ambiguous AI intuitions going on in the interpreter... its
just me whining out loud and realizing that explicit really is better
than implicit... much of the time.
kind regards,
m harris
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.lang.python
csiph-web