[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Questions on closure environment capture
- Subject: Re: Questions on closure environment capture
- From: Quentin Carbonneaux <quentin@xxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Thu, 3 May 2018 07:03:12 +0000
- To: myrddin-dev@xxxxxxxxxxxxxx
On Thu, May 03, 2018 at 12:14:31PM +0800, vimacs wrote:
> Hi,
>
> I'm trying to use the closure in Myrddin, but I'm confused about the
> implementation of it and the so-called environment capture.
>
> Here are some code in my program.
Hi,
Thank your for your very interesting questions.
> So what is the semantic and implementation of closure and environment
> capture? Is there an easy way to implement the functions I said above?
In a nutshell, if you want to do anything "fancy" (i.e., anything that is
not simple Pascal-style nested functions) use std.fndup().
Your example can be made to work by changing it like so:
const f_ = {t
-> std.fndup({x; -> x+t})
}
[...]
f[i] = std.fndup({x
-> x+i
})
What fndup does is that it takes your closure whose environment
is currently on the *stack* and moves it to the heap.
Since the environements are by default on the stack, your f_()
function cannot work properly because you return a closure whose
environment has been destroyed (because f_ returned).
Now, for the f[i] = {x; -> x+i}. The reason why you only "see"
the last closure (with i = 3) is that the compiler turns your
code into something like this:
const main = {
var __myclosure_env
var i, j
var f: (x:int -> int)[8]
var g
for ...
__my_closure_env = i
f[i] = (&__my_closure_env, __code_ptr)
;;
[...]
}
As you can see, there is only one local environment for the *syntactic*
closure, not one per dynamically-created closure. It might be possible
to create one environemnt per *dynamic* closure, but that would require
dynamic stack allocation. I am not sure what Ori thinks about it.
Let me know if this makes sense.
And Ori, please feel free to correct/enrich the explanation.
Best,
- Q