[erlang-questions] Improve $handle_undefined_function

Vlad Dumitrescu vladdu55@REDACTED
Tue Jan 22 13:30:30 CET 2013


Ok, I see. I had lost track of who suggested the example originally.

I suppose that the functions listed in -attr() would have to be included in
an -export() too if they are to be public?

regards,
Vlad


On Tue, Jan 22, 2013 at 1:25 PM, Loïc Hoguin <essen@REDACTED> wrote:

> On 01/22/2013 01:10 PM, Vlad Dumitrescu wrote:
>
>> On Tue, Jan 22, 2013 at 1:02 PM, Loïc Hoguin <essen@REDACTED
>> <mailto:essen@REDACTED>> wrote:
>>
>>     On 01/22/2013 12:57 PM, Vlad Dumitrescu wrote:
>>
>>         Hi,
>>
>>         On Tue, Jan 22, 2013 at 12:10 PM, Loïc Hoguin
>>         <essen@REDACTED <mailto:essen@REDACTED>
>>         <mailto:essen@REDACTED <mailto:essen@REDACTED>>> wrote:
>>
>>              On 01/22/2013 07:34 AM, Björn Gustavsson wrote:
>>
>>                  Why not use the existing -export() attribute and write
>> like
>>
>>                  this:
>>
>>                  -export([monitor/2,demonitor/_**___1]).
>>
>>
>>
>>                  monitor(process, Pid) ->
>>                       do_something.
>>
>>                  demonitor(Pid) ->
>>                       do_something_else().
>>
>>                  So what would be the advantage of your version?
>>
>>
>>              It still allows Evan Miller to write this:
>>
>>              -attr([first_name/1, last_name/1, ...]).
>>
>>              $handle_undefined_function(F, [Model]) ->
>>                   {_, Value} = lists:keyfind(F, 1, Model),
>>                   Value.
>>
>>
>>         I'm sorry, but I don't think you are answering Björn's question.
>> For
>>         this particular case, why not write regular Erlang like
>>
>>         first_name(Model) -> get(first_name, Model).
>>         last_name(Model) -> get(last_name, Model).
>>         get(F, [Model]) ->
>>               {_, Value} = lists:keyfind(F, 1, Model),
>>               Value.
>>         which is much clearer to understand. One argument might be that
>>         there is
>>         some duplication, but I think that it could be handled with much
>>         more
>>         elegance if we had abstract patterns implemented.
>>
>>         Do you have a more relevant example where using
>>         $handle_undefined_function gives significant advantage?
>>
>>
>>     That's a question about $handle_undefined_function in general, not
>>     about this specific implementation proposal. Björn is the one who
>>     wrote the current implementation that's now in master, I don't have
>>     to tell him what can be done with it, he knows. I do have to tell
>>     him how implementing it this way improves the usage, though. Which
>>     is the sole reason of this thread.
>>
>>
>> Maybe I'm confused, but your answer would make 100% sense if Björn's
>> question would have been
>>
>> "
>>    Why not use the existing -export() attribute and write like this:
>>          -export([monitor/2,demonitor/**1]).
>> $handle_undefined_function(__**monitor, [process, Pid]) ->
>>              do_something();
>>          $handle_undefined_function(__**demonitor, Pid) ->
>>
>>              do_something_else().
>> "
>>
>> My question is a follow-up on his own formulation, where your suggestion
>> is compared with an implementation not using $handle_undefined_function
>> at all.
>>
>
> And I answered it based on known potential uses. The snippet you quote was
> made to demonstrate the flaws in the current implementation, not to
> demonstrate an interesting use of the feature. It can be demonstrated using
> Evan's example too, for example:
>
> $handle_undefined_function(F, [Model]) when is_list(Model) ->
>
>     {_, Value} = lists:keyfind(F, 1, Model),
>     Value;
>
> $handle_undefined_function(F, Args) ->
>     error_handler:raise_undef_**exception(?MODULE, F, Args).
>
> This would be an incorrect implementation of Evan's use for it, and
> nothing about it says "It's obvious!". And yet it's still wrong. Correct
> implementation would be:
>
> $handle_undefined_function(F, [Model]) when is_list(Model) ->
>
>     {_, Value} = lists:keyfind(F, 1, Model),
>     Value;
> $handle_undefined_function(F, Args) ->
>     case lists:member({F, length(Args)},
>             [{first_name, 1}, {last_name, 1}, ...]) of
>         true -> erlang:error(badarg);
>         false -> error_handler:raise_undef_**exception(?MODULE, F, Args)
>     end.
>
> With my proposal he can write:
>
> -attr([first_name/1, last_name/1]).
>
> $handle_undefined_function(F, [Model]) when is_list(Model) ->
>
>     {_, Value} = lists:keyfind(F, 1, Model),
>     Value.
>
> This makes error_handler properly handle undef errors, reduces the code
> needed to use the feature, allow tools to behave nicely when using the
> feature, etc.
>
> As for why Evan would use $handle_undefined_function instead of creating
> many functions, that's for him to decide. But both implementations of
> $handle_undefined_function allow all known uses of the feature, yet only
> one gets error handling and tools support straight.
>
>
> --
> Loïc Hoguin
> Erlang Cowboy
> Nine Nines
> http://ninenines.eu
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130122/5ad34801/attachment.htm>


More information about the erlang-questions mailing list