Erlang/OTP Forums

Author Message

<  Erlang  ~  Code replacement and fun expressions

jwatte
Posted: Fri Mar 19, 2010 10:05 pm Reply with quote
User Joined: 10 Feb 2010 Posts: 34
Is it the case that any fun closure will become invalid once the module it was defined in has been reloaded twice?

Specifically:

Code:

-module(foo).
-export([make_fun/1, mutate/2]).

make_fun(Var) -> fun(X) -> foo:mutate(Var, X) end.

mutate(A, B) -> A+B.



If I build this and run it, and then reload foo twice, will a fun returned by make_fun/1 stop working?

I guess the question boils down to whether the implementation generates code for the lambda, or just generates an environment with a pointer to pre-generated code?
View user's profile Send private message
bpuzon
Posted: Sat Mar 20, 2010 11:56 am Reply with quote
User Joined: 05 Aug 2009 Posts: 23 Location: Cracow, Poland
Let's say you've done this:
Code:
F = foo:make_fun(bar)


If you use dbg, you will see that F(bar) translates to:
Code:
(<0.380.0>) call foo:'-makefun/1-fun-0-'(bar,bar)


You will invalidate F if the definition of foo:'-makefun/1-fun-0-' changes somehow. In particular, you can't change the fun's definition and, inside make_fun/1, you can't define any new funs before the one you already have.

However, I wouldn't rely on the current fun implementation rules and rather assume that any changes to make_fun will require the invalidation of F.

_________________
Saludos,
Bartłomiej Puzoń
Erlang Solutions
View user's profile Send private message Visit poster's website
jwatte
Posted: Sat Mar 20, 2010 3:49 pm Reply with quote
User Joined: 10 Feb 2010 Posts: 34
Thanks for the hint about the debugger!

Then there's a follow-up question: the "mochiweb" application creates a fun() for the callback for web requests (the fun then calls a named/module-qualified function within the module), and starts an automatic reloader application that re-loads modules that have been changed.

I then assume this then means that you can only re-load your callback module once, before that fun will be invalidated and all future requests will be invalid?
View user's profile Send private message
bpuzon
Posted: Sat Mar 20, 2010 4:11 pm Reply with quote
User Joined: 05 Aug 2009 Posts: 23 Location: Cracow, Poland
Could you provide a short example of the mochiweb's call sequence? Your description is a bit too complicated for me.

_________________
Saludos,
Bartłomiej Puzoń
Erlang Solutions
View user's profile Send private message Visit poster's website
jwatte
Posted: Sat Mar 20, 2010 4:45 pm Reply with quote
User Joined: 10 Feb 2010 Posts: 34
Here is the mochiweb skeleton module for a web app, which ends up being the module where you're supposed to develop your URL path dispatch:

Code:

-module(skel_web).
-author('author <author@example.com>').

-export([start/1, stop/0, loop/2]).

%% External API

start(Options) ->
    {DocRoot, Options1} = get_option(docroot, Options),
    Loop = fun (Req) ->
                   ?MODULE:loop(Req, DocRoot)
           end,
    mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).

stop() ->
    mochiweb_http:stop(?MODULE).

loop(Req, DocRoot) ->
    "/" ++ Path = Req:get(path),
    case Req:get(method) of
        Method when Method =:= 'GET'; Method =:= 'HEAD' ->
            case Path of
                _ ->
                    Req:serve_file(Path, DocRoot)
            end;
        'POST' ->
            case Path of
                _ ->
                    Req:not_found()
            end;
        _ ->
            Req:respond({501, [], []})
    end.


Specifically, "Loop" is a fun expression defined in this module, which calls this module itself. It's an argument to the mochiweb framework -- each time a request comes in, mochiweb will spawn a new process and call the fun within the context of that process to handle the request.

I was seeing a problem where the server would stop responding after updating and re-compiling this module a few times. It seems pretty clear that the reason is that the fun passes as argument is becoming invalidated when the initial version of the module goes from "old" to "purged."

In most other languages with closures (Python, JavaScript, Scheme, etc), the code for a closure lives "forever," and module definitions (and parts thereof, such as individual versions of function definitions) are simply garbage collected like anything else. This different behavior of Erlang confused me as a newbie until I understood what's going on.
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum