[erlang-questions] Variable bindings

Tyron Zerafa <>
Mon Jan 28 19:23:53 CET 2013


>>The problem is that funs don't normally _have_ code available
>>unless you compile the containing module with a special option.

>>Have you considered the alternative of accepting the *source code*
>>of a fun and parsing that?

I have considered this option but as far as possible we do not want to
change any syntax. The final objective is to have the same spawn(N,F)
syntax but which is capable of accepting and executing F on the remote node
irrelevant of whether the code is there or not.

>>Er, the free variables of a fun are _not_ the variables that are
>>in scope at its point of creation, they are that subset of those
>>variables that are *used* inside the fun.

>>What a fun _is_, conceptually, is a tuple containing a code reference
>>and a set of variable bindings.  If someone gives you a fun, you know
>>exactly what the values for those variables are because they are right
>>there.  A fun does not point back to the stack frame of its creator.

Our intention is to change exactly this; i.e. what fun actually _is_. We
are trying to change from the current ETF for fun to one containing also
the function's code tree or some other presentation. Since fun does not
point back to the stack frame, our current implementation is passing the
required environment variables as part of the fun's parameter list, thus
shadowing the original one. In practice

*λx:x+y *
*
*
becomes
*
*
*λx,y:x+y *<- this gets serialized and transferred. *
*

In regards to version consistency, we are not using the original module
name, but renaming to  This would not break anything on the
remote node. It goes without saying that any code transferred to the remote
node reflects this change in mod name.

Thanks for your insight :)





On Mon, Jan 28, 2013 at 12:40 AM, Richard O'Keefe <> wrote:

>
> On 28/01/2013, at 12:11 AM, Tyron Zerafa wrote:
>
> > I want to build a call which accepts a fun, extracts all of its code and
> dependencies, pass everything over to a remote node and execute it there.
>
> The problem is that funs don't normally _have_ code available
> unless you compile the containing module with a special option.
>
> Have you considered the alternative of accepting the *source code*
> of a fun and parsing that?
>
> > The only problem I am having is extracting the value of the free vars of
> such fun.
>
> Er, the free variables of a fun are _not_ the variables that are
> in scope at its point of creation, they are that subset of those
> variables that are *used* inside the fun.
>
> What a fun _is_, conceptually, is a tuple containing a code reference
> and a set of variable bindings.  If someone gives you a fun, you know
> exactly what the values for those variables are because they are right
> there.  A fun does not point back to the stack frame of its creator.
>
> Let's take a look at a tiny example.
>
> foo(X, Y) ->
>     M = (X+Y)/2,
>     fun (Z) -> {Z,M} end.
>
> Now let's look at the BEAM code.
>
> {function, foo, 2, 2}.
>   {label,1}.
>     {func_info,{atom,foo},{atom,foo},2}.
>   {label,2}.
>     % add Y to X; put the result back in X
>     {gc_bif,'+',{f,0},2,[{x,0},{x,1}],{x,0}}.
>     % check that there is room for two floats
>     {test_heap,{alloc,[{words,0},{floats,1}]},2}.
>     % convert X to floating point (in FR 0)
>     {fconv,{x,0},{fr,0}}.
>     % convert 2 to floating point (in FR 1)
>     %?? Why is this not done at compile time?
>     {fconv,{integer,2},{fr,1}}.
>     fclearerror.
>     % Divide FR 0 by FR 1 and put the result in FR 0.
>     {bif,fdiv,{f,0},[{fr,0},{fr,1}],{fr,0}}.
>     {fcheckerror,{f,0}}.
>     % Now that we know all went well, box the result
>     % and put it back in X.
>     {fmove,{fr,0},{x,0}}.
>     {'%live',1}.
>     % Create a fun, copying X (but not what X points to)
>     % into it.
>     {make_fun2,{f,8},0,98308069,1}.
>     return.
>
> {function, '-foo/2-fun-0-', 2, 8}.
>   {label,7}.
>     {func_info,{atom,foo},{atom,'-foo/2-fun-0-'},2}.
>     % {f,8} in the make_fun2 instruction points here.
>   {label,8}.
>     % Check that there is room for a 2-tuple
>     {test_heap,3,2}.
>     % start to create it, and let X2 point to it.
>     {put_tuple,2,{x,2}}.
>     % put in Z
>     {put,{x,0}}.
>     % put in M
>     {put,{x,1}}.
>     % move X2 down to X0
>     {move,{x,2},{x,0}}.
>     % return X0
>     return.
>
> > I was thinking about adding these to the parameter list of the fun,
>
> As the code shows, the (selected) free variables _are_ hidden
> parameters of the fun.
>
> > i.e shadowing the respective vars.
>
> ?
>
> Finding the dependencies of a fun, at least those not already
> compiled inline, can be done from its BEAM code.  You do not
> need the source code.  What you cannot get, either way, is
> which _versions_ of the modules used the code depends on.
>
> And that creates a big problem.
>
> On local node L, send F1 to remote node R.
> F1 needs module M.
> Ensure that R has M loaded.
> But M on R is a completely different module from M on L.
> So send L to R as well and have it install that.
> Congratulations, you just broke everything else on R
> that used M.
>
> If you can manage version consistency to the point at
> which every node you try to send stuff to has the same
> versions of all the relevant modules you need, then you
> don't need to extract dependencies at run time.
> If you can't do that, it's not going to work anyway.
>
> This whole sending-code-to-a-remote-node business is to be done
> with *extreme* vigilant trepidation, if at all.
>
> Do you *really* want me to be able to call
>    your_module:your_handy_function(fun () -> halt() end)
>
> Consider whether it is possible to devise a *sublanguage* of
> trustworthy code.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130128/1a2864d9/attachment.html>


More information about the erlang-questions mailing list