Execute module code from stored anonymous function

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Execute module code from stored anonymous function

Nuku Ameyibor
Dear List ,

i run into an issue where i was storing an anonymous function in mnesia  to be executed later .
F=fun(test) ->mprocess:process_template(test)end.


however  as soon as i make some changes to the mprocess module  and upgrade the module i get a ** exception error: bad function error when i retrieve the fun and try to execute which i assume is because of the difference in the module versions .
Is there a way of making the stored fun execute the code and not have version conflicts .


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Execute module code from stored anonymous function

Dmytro Lytovchenko
In your case the pointer to function is stored internally and it goes extinct when module is gone.
If you make it calculate function at runtime by, say, calling apply(mprocess, process_template, [test]), then it should work.

sön 11 sep. 2016 kl 08:57 skrev Nuku Ameyibor <[hidden email]>:
Dear List ,

i run into an issue where i was storing an anonymous function in mnesia  to be executed later .
F=fun(test) ->mprocess:process_template(test)end.


however  as soon as i make some changes to the mprocess module  and upgrade the module i get a ** exception error: bad function error when i retrieve the fun and try to execute which i assume is because of the difference in the module versions .
Is there a way of making the stored fun execute the code and not have version conflicts .

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Execute module code from stored anonymous function

Nuku Ameyibor
thanks for quick reply .
will give it a shot .

On Sun, Sep 11, 2016 at 7:08 AM, Dmytro Lytovchenko <[hidden email]> wrote:
In your case the pointer to function is stored internally and it goes extinct when module is gone.
If you make it calculate function at runtime by, say, calling apply(mprocess, process_template, [test]), then it should work.

sön 11 sep. 2016 kl 08:57 skrev Nuku Ameyibor <[hidden email]>:
Dear List ,

i run into an issue where i was storing an anonymous function in mnesia  to be executed later .
F=fun(test) ->mprocess:process_template(test)end.


however  as soon as i make some changes to the mprocess module  and upgrade the module i get a ** exception error: bad function error when i retrieve the fun and try to execute which i assume is because of the difference in the module versions .
Is there a way of making the stored fun execute the code and not have version conflicts .

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Execute module code from stored anonymous function

Pierre Fenoll-2
In your case the pointer to function is stored internally and it goes extinct when module is gone.

Why is this the behavior? I would expect the fun to properly call the latest version of the module's code if not purged,
throwing an exception otherwise, not "just throw because version changed".

Why disallow funs to directly reference version-changing code?
(indirectly because fun () -> apply(M, F, A) end is still possible)


I am surprised & interested in the reasons behind having 

* fun () -> mod:fname(Arg1, Arg2, ...) end
* fun () -> erlang:apply(mod, fname, [Arg1, Arg2, ...]) end

be semantically different! 



Cheers,
-- 
Pierre Fenoll


On 11 September 2016 at 09:27, Nuku Ameyibor <[hidden email]> wrote:
thanks for quick reply .
will give it a shot .

On Sun, Sep 11, 2016 at 7:08 AM, Dmytro Lytovchenko <[hidden email]> wrote:
In your case the pointer to function is stored internally and it goes extinct when module is gone.
If you make it calculate function at runtime by, say, calling apply(mprocess, process_template, [test]), then it should work.

sön 11 sep. 2016 kl 08:57 skrev Nuku Ameyibor <[hidden email]>:
Dear List ,

i run into an issue where i was storing an anonymous function in mnesia  to be executed later .
F=fun(test) ->mprocess:process_template(test)end.


however  as soon as i make some changes to the mprocess module  and upgrade the module i get a ** exception error: bad function error when i retrieve the fun and try to execute which i assume is because of the difference in the module versions .
Is there a way of making the stored fun execute the code and not have version conflicts .

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Execute module code from stored anonymous function

Tony Rogvall-2
A local fun ”belongs” to the code module where it is defined.
So the problem is that the definition it self is purged out of the system.

This is not the case with fun mod:fun/a, for example fun erlang:integer_to_list/1 is
just referring to an export entry.

You can still use fun’s to refer to the old version of the definition ( in the old module ) as
long as they are not purged. I some time use this fact to create transaction funs that survive
ONE code reload while executing for example rules that are compiled.

The example below let you create a global ets store for procedures.

> etsfun:create().
> etsfun:store_procedure(f, etsfun:procedure_global1()).
> etsfun:call_procesure(f, 1).
”1”

In this case you reload the ’etsfun’ module as many time as you like since,
the global1 function is not defined in the etsfun module.

> etsfun:create().
> etsfun:store_procedure(f, etsfun:procedure_global2()).
> etsfun:call_procedure(f, 1).
”1”

If you just recompile+reload this module without changing anything that will allow you to
reload any number of times as well. But if you change the module a tine bit
by for example adding a blank in a string ( must be in code ) then you can still call the
function since the old version is still there.
But change code one more recompile+reload and the original fun is purged from the system
and the call will crash, as expected.

This last example with a local function that talks a bit, show this a bit more.

> etsfun:create().
> etsfun:store_procedure(f, etsfun:procedure_local()).
> etsfun:call_procedure(f, 1).
fun 1

Now change the body of the procedure_local() to the one with ”hej” and recompile/reload once.

> etsfun:call_procedure(f, 1).
fun 1

Same result, the same fun. But if you change again and recompile/reload this will crash.

and finally

> etsfun:store_procedure(f, etsfun:procedure_local()).
> etsfun:call_procedure(f, 1).
hej  1

and the new definition is stored.




-module(etsfun).
-compile(export_all).

create() ->
    ets:new(etsfun, [named_table, public]).

store_procedure(Key, F) ->
    ets:insert(etsfun, {Key,F}).

call_procedure(Key,Arg) ->
    [{_,F}] = ets:lookup(etsfun, Key),
    F(Arg).

procedure_global1() ->
    fun erlang:integer_to_list/1.

procedure_global2() ->
    fun(X) ->
            erlang:integer_to_list(X)
    end.

procedure_local() ->
    fun(X) ->
            my_local_func(X)
    end.

%% my_local_func(X) -> io:format("hej  ~w\n", [X]).
my_local_func(X) -> io:format("fun ~w\n", [X]).





> On 11 sep 2016, at 10:39, Pierre Fenoll <[hidden email]> wrote:
>
> > In your case the pointer to function is stored internally and it goes extinct when module is gone.
>
> Why is this the behavior? I would expect the fun to properly call the latest version of the module's code if not purged,
> throwing an exception otherwise, not "just throw because version changed".
>
> Why disallow funs to directly reference version-changing code?
> (indirectly because fun () -> apply(M, F, A) end is still possible)
>
>
> I am surprised & interested in the reasons behind having
>
> * fun () -> mod:fname(Arg1, Arg2, ...) end
> * fun () -> erlang:apply(mod, fname, [Arg1, Arg2, ...]) end
>
> be semantically different!
>
>
>
> Cheers,
> --
> Pierre Fenoll
>
>
> On 11 September 2016 at 09:27, Nuku Ameyibor <[hidden email]> wrote:
> thanks for quick reply .
> will give it a shot .
>
>
> On Sun, Sep 11, 2016 at 7:08 AM, Dmytro Lytovchenko <[hidden email]> wrote:
> In your case the pointer to function is stored internally and it goes extinct when module is gone.
> If you make it calculate function at runtime by, say, calling apply(mprocess, process_template, [test]), then it should work.
>
> sön 11 sep. 2016 kl 08:57 skrev Nuku Ameyibor <[hidden email]>:
> Dear List ,
>
> i run into an issue where i was storing an anonymous function in mnesia  to be executed later .
> F=fun(test) ->mprocess:process_template(test)end.
>
>
> however  as soon as i make some changes to the mprocess module  and upgrade the module i get a ** exception error: bad function error when i retrieve the fun and try to execute which i assume is because of the difference in the module versions .
> Is there a way of making the stored fun execute the code and not have version conflicts .
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

signature.asc (817 bytes) Download Attachment