views:

199

answers:

4

I come from a Java and Ruby background and I was wondering if there is any equivalent of "method_missing" in Erlang. I have looked at the documentation and the closest I can see is the use of erl_eval and erl_parse, but I wanted to know if there is any other way?

A: 

I'm using a similar pattern on the calling side where a module may supply a log level classification function (which may return invalid results). I do it like this:

-spec categorize(atom(), integer()) -> log_classification().
categorize(Module, Code) ->
    case catch(Module:ns_log_cat(Code)) of
        info -> info;
        warn -> warn;
        crit -> crit;
        _ -> info % Anything unknown is info (this includes {'EXIT', Reason})
        end.

Since there isn't a method (in general, you could certainly create an OO behavior and implement it with messages and then have method_missing, the callee doesn't know I attempted anything, so it can't interpret it.

Dustin
Is this the same as a default clause in a case statement??
Zubair
In this case, I'm matching three known good values and then dealing with any other case (including exceptions and exits) as a default. I use `_` because I don't care about the results.
Dustin
+10  A: 

There is the 'error_handler' module which is called when you attempt to call an undefined function.

process_flag(error_handler, Module).

The module needs to export undefined_function/3 and undefined_lambda/3. You can see how this should be implemented in the standard handler module, error_handler.

You need to be careful in your own error_handler not to break the standard code loading system. Erlang usually tries to load the module from an undefined function error and re-run the function before giving up and signalling an error. You usually want to try the standard error_handler first and fall back to your new behaviour if that fails.

archaelus
+1: thanks for this!
jldupont
I'll look into this more
Zubair
+3  A: 

If you are into "defensive coding", you can call Module:module_info(exports) to see if the function you're about to call is exported or not.

Zed
Useful tip, I tried this and it does provide useful information. Is there any way I can dynamically add a method to this list (to a module I mean) then, as that could be useful
Zubair
Check out smerl: http://code.google.com/p/erlyweb/source/browse/trunk/src/smerl/smerl.erl
Zed
+1  A: 

Erlang has functions not methods and generally trying to call an undefined function is considered to be an error.

The compiler generates an error if you try to call a non-existent function within the same module. Trying to call a function in another module will generate an error at runtime, the undef error. How you wish to handle such an error depends on your application.

rvirding
So this looks promising. So does this mean that a "function_missing" method could be created for external modules which is invoked at runtime?
Zubair
Yes, it could. See @archaelus answer earlier for more details. Be warned though that messing with the error_handler could completely ruin the automatic code loading and really mess up the system if it is not 100% right.
rvirding