November 26, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Horne | Steve Horne wrote: > On Sat, 25 Nov 2006 14:41:49 +0100, Michael Butscher <mbutscher@gmx.de> wrote: > > >Especially a closure would have direct access to the current value of local variables of the outer function (if it exists yet) which is not the case for frozen functions. > > That's not the definition of closures I was taught. A closure would behave exactly as your frozen function does - it does not have direct access to the current value since it keeps a copy of the value at the time when the definition was 'executed'. I could not find yet such a clear definition, e.g. http://en.wikipedia.org/wiki/Closure_(computer_science) says A closure typically comes about when one function is declared entirely within the body of another, and the inner function refers to local variables of the outer function. At runtime, when the outer function executes, a closure is formed. It consists of the inner function's code and references to any variables in the outer function's scope that the closure needs. which is not clear about that. > So for instance, in Python (which does use closures)... > > a = 5 > fn = lambda : a > a = 6 > print fn() > > The output should be 5, not 6 - the value when the lambda expression was evaluated. Have you tried that? With Python 2.5 in an interactive session, I get: >>> def test(): a = 5 fn = lambda : a a = 6 print fn() >>> test() 6 Michael |
November 26, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frank Benoit (keinfarbton) | Frank Benoit (keinfarbton) wrote:
> This is the case for Java also. If you define a anonymous class in a method it can access the local variable and arguments of the surrounding method. The compiler forces them to be final.
My idea was inspired by this. As D has nothing like final, I thought a copy of the outer variables would do as well.
Michael
|
November 26, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michael Butscher | > My idea was inspired by this. As D has nothing like final, I thought a copy of the outer variables would do as well.
I am not completely sure, but I think this is the way java implements this. If you imagine that the method can be called multiple times and the instantiated object can work with different final values, it seams the values are copied into the object instance.
|
November 27, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michael Butscher | On Sun, 26 Nov 2006 15:28:03 +0100, Michael Butscher <mbutscher@gmx.de> wrote: >Steve Horne wrote: >> So for instance, in Python (which does use closures)... >> >> a = 5 >> fn = lambda : a >> a = 6 >> print fn() >> >> The output should be 5, not 6 - the value when the lambda expression was evaluated. > >Have you tried that? With Python 2.5 in an interactive session, I get: > >>>> def test(): > a = 5 > fn = lambda : a > a = 6 > print fn() > > >>>> test() >6 No, I didn't test, and now I'm a bit embarrassed, and confused. I have tonnes of code that uses lambdas, and I'm sure some depends on this behaviour. Code which is heavily used and which all seems to work. Yet suddenly, I can't get a simple example to work right. All I can say is that something's going on in Python that I don't know about. I've checked my favorite compiler-stuff text (Modern Compiler Design, Dick Grune et al) and theres a section (6.3.5.5 Currying a routine) that seems to agree with my closure definition more-or-less. But this is about currying, not inner functions. In the same book, section 6.3.5.3 is directly relevant (title "Returning a nested routine as a value"). It describes the using-dead-variables issue, but actually suggests keeping the local variables for the outer function in a heap frame rather than on the stack. But... 1 This is the variables for the outer function, not the inner function. You put those variables in the stack frame whether the inner function object is actually created or not, and several inner function objects could be created that all refer to the same stack frame. 2 It doesn't use the term closure to describe this. So basically, I thought I knew what I was talking about, but now I'm not so sure. Maybe Python is doing the (1) thing, but that leaves me wondering how come my existing code is working. Incidentally, Amazon seems to have the full text of the book if you want to check exactly what it says, but stepping through the pages one-by-one to get to the relevant section (around page 490-ish) is painful. -- Remove 'wants' and 'nospam' from e-mail. |
November 27, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Horne | On Mon, 27 Nov 2006 07:40:00 +0000, Steve Horne <stephenwantshornenospam100@aol.com> wrote: >1 This is the variables for the outer function, not the inner > function. You put those variables in the stack frame whether > the inner function object is actually created or not, and > several inner function objects could be created that all refer > to the same stack frame. Ooops - that's... to the same *heap* frame. -- Remove 'wants' and 'nospam' from e-mail. |
November 27, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Horne | Steve Horne wrote: > But... > > 1 This is the variables for the outer function, not the inner > function. You put those variables in the stack frame whether > the inner function object is actually created or not, and > several inner function objects could be created that all refer > to the same stack frame. > > 2 It doesn't use the term closure to describe this. > > So basically, I thought I knew what I was talking about, but now I'm not so sure. > > Maybe Python is doing the (1) thing, but that leaves me wondering how come my existing code is working. Before closures were introduced in Python (about 2.2 or so), it was a common idiom to write: lambda a=a: ... to access an outer variable a. Maybe you are using something like that. > Incidentally, Amazon seems to have the full text of the book if you want to check exactly what it says, but stepping through the pages one-by-one to get to the relevant section (around page 490-ish) is painful. This would be really tedious, especially with my dialup internet connection. Michael |
November 27, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Horne | Steve Horne wrote:
> On Sun, 26 Nov 2006 15:28:03 +0100, Michael Butscher
> <mbutscher@gmx.de> wrote:
>
>
>>Steve Horne wrote:
>
>
>>>So for instance, in Python (which does use closures)...
>>>
>>>a = 5
>>>fn = lambda : a
>>>a = 6
>>>print fn()
>>>
>>>The output should be 5, not 6 - the value when the lambda expression
>>>was evaluated.
>>
>>Have you tried that? With Python 2.5 in an interactive session, I get:
>>
>>
>>>>>def test():
>>
>> a = 5
>> fn = lambda : a
>> a = 6
>> print fn()
>>
>>
>>
>>>>>test()
>>
>>6
>
>
> No, I didn't test, and now I'm a bit embarrassed, and confused.
>
> I have tonnes of code that uses lambdas, and I'm sure some depends on
> this behaviour. Code which is heavily used and which all seems to
> work. Yet suddenly, I can't get a simple example to work right.
>
> All I can say is that something's going on in Python that I don't know
> about.
>
>
> I've checked my favorite compiler-stuff text (Modern Compiler Design,
> Dick Grune et al) and theres a section (6.3.5.5 Currying a routine)
> that seems to agree with my closure definition more-or-less.
>
> But this is about currying, not inner functions.
>
> In the same book, section 6.3.5.3 is directly relevant (title
> "Returning a nested routine as a value"). It describes the
> using-dead-variables issue, but actually suggests keeping the local
> variables for the outer function in a heap frame rather than on the
> stack.
>
> But...
>
> 1 This is the variables for the outer function, not the inner
> function. You put those variables in the stack frame whether
> the inner function object is actually created or not, and
> several inner function objects could be created that all refer
> to the same stack frame.
>
> 2 It doesn't use the term closure to describe this.
>
> So basically, I thought I knew what I was talking about, but now I'm
> not so sure.
>
> Maybe Python is doing the (1) thing, but that leaves me wondering how
> come my existing code is working.
>
> Incidentally, Amazon seems to have the full text of the book if you
> want to check exactly what it says, but stepping through the pages
> one-by-one to get to the relevant section (around page 490-ish) is
> painful.
>
In my understanding, closures are like functions which carry state along with them. Like objects but with only a single method: opCall().
in Lua syntax:
function make_adder()
local sum = 0;
return function(n) sum = sum + n; return sum; end
end
x = make_adder()
print(x(5))
5
print(x(10))
15
the function returned is a closure of the environment in make_adder.
When the closure carries along the sum value it is called lambda lifting. (sum is called an 'upvalue')
Currying simply allows composition of larger functions from smaller (incomplete) ones. In Lua:
function f(a,b) return a + b; end
to curry f with the value of 1:
x = function(b) return f(1 , b); end
or more generally:
def curry(fn,val)
return function(b) return fn(val,b) end
end
Coroutines are interesting as they also exhibit the same state-capture as closures. Here is an equivalent example in Lua:
function adder(sum)
while(true) do
sum = sum + coroutine.yield(sum)
end
end
function make_adder()
return coroutine.create(adder);
end
a = make_adder()
ok,x = coroutine.resume( a, 5 )
print( x )
ok, x = coroutine.resume( a, 10 )
print( x )
Off the top of my head, so quite probably errors here.
I ran my code in Lua 5.1, though.
-DavidM
|
November 27, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michael Butscher | On Mon, 27 Nov 2006 20:04:10 +0100, Michael Butscher <mbutscher@gmx.de> wrote: >Steve Horne wrote: >> Maybe Python is doing the (1) thing, but that leaves me wondering how come my existing code is working. > >Before closures were introduced in Python (about 2.2 or so), it was a common idiom to write: > >lambda a=a: ... > >to access an outer variable a. Maybe you are using something like that. No. I used to, but it was a big relief when I didn't need to any more. I'm not so sure now that I change variables much after using them like this. -- Remove 'wants' and 'nospam' from e-mail. |
November 28, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Medlock | David Medlock wrote:
[What are closures?]
> In my understanding, closures are like functions which carry state along with them. Like objects but with only a single method: opCall().
>
> in Lua syntax:
>
> function make_adder()
> local sum = 0;
> return function(n) sum = sum + n; return sum; end
> end
What happens while the outer function is "alive" yet?
E.g. something like (I don't know Lua, therefore I guessed syntax):
function test()
local sum = 0;
local x = function(n) sum = sum + n; return sum; end
sum = 5;
print(x(5));
end
Does this print 5 or 10?
Michael
|
November 28, 2006 Re: Idea: "Frozen" inner function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Horne | Steve Horne wrote:
> On Mon, 27 Nov 2006 20:04:10 +0100, Michael Butscher <mbutscher@gmx.de> wrote:
>
> >Steve Horne wrote:
>
> >> Maybe Python is doing the (1) thing, but that leaves me wondering how come my existing code is working.
> >
> >Before closures were introduced in Python (about 2.2 or so), it was a common idiom to write:
> >
> >lambda a=a: ...
> >
> >to access an outer variable a. Maybe you are using something like that.
>
> No. I used to, but it was a big relief when I didn't need to any more.
>
> I'm not so sure now that I change variables much after using them like this.
Me too :-)
It seems that full-blown closures with live access to outer variables (as long as the outer function exists) are of much rarer need than one might think at first.
Michael
|
Copyright © 1999-2021 by the D Language Foundation