Erlang и method_missing - PullRequest
       18

Erlang и method_missing

2 голосов
/ 14 января 2010

Я пришел из Java и Ruby, и мне было интересно, есть ли какой-нибудь эквивалент "method_missing" в Erlang.Я посмотрел на документацию, и самое близкое, что я вижу, это использование erl_eval и erl_parse, но я хотел знать, есть ли другой способ?

Ответы [ 5 ]

18 голосов
/ 15 января 2010

Существует модуль 'error_handler', который вызывается при попытке вызвать неопределенную функцию.

process_flag(error_handler, Module).

Модуль должен экспортировать undefined_function/3 и undefined_lambda/3. Вы можете увидеть, как это должно быть реализовано в стандартном модуле обработчика, error_handler.

Вы должны быть осторожны в своем собственном error_handler, чтобы не сломать стандартную систему загрузки кода. Erlang обычно пытается загрузить модуль из-за неопределенной ошибки функции и перезапустить функцию, прежде чем отказаться и сообщить об ошибке. Обычно вы сначала хотите попробовать стандартный обработчик ошибок и в случае сбоя вернитесь к своему новому поведению.

3 голосов
/ 08 марта 2013

archaelus указал в хорошем направлении, но если вы предпочитаете не вмешиваться в error_handler, он поддерживает красивую процедуру обратного вызова, уведомляющую вызываемый модуль, что была попытка вызвать неопределенную функцию, что кажется довольно удобным .

https://github.com/erlang/otp/blob/maint/lib/kernel/src/error_handler.erl#L139

Итак, если вы добавите это в модуль:

'$handle_undefined_function'(Func, Args) ->
     io:format("Called undefined function '~p' with args ~p.~n", [Func, Args]).

Он будет распечатывать сообщение всякий раз, когда будет выполнен вызов неопределенной функции в этом модуле.

3 голосов
/ 15 января 2010

Если вы занимаетесь «защитным кодированием», вы можете вызвать Module:module_info(exports), чтобы узнать, экспортируется ли функция, которую вы собираетесь вызвать, или нет.

1 голос
/ 16 января 2010

Эрланг имеет функции, а не методы, и обычно попытка вызова неопределенной функции считается ошибкой.

Компилятор генерирует ошибку, если вы пытаетесь вызвать несуществующую функцию в том же модуле. Попытка вызова функции в другом модуле вызовет ошибку во время выполнения, ошибку undef. То, как вы хотите справиться с такой ошибкой, зависит от вашего приложения.

0 голосов
/ 15 января 2010

Я использую аналогичный шаблон на вызывающей стороне, где модуль может предоставлять функцию классификации на уровне журнала (которая может возвращать недопустимые результаты). Я делаю это так:

-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.

Поскольку метода нет (в общем, вы, безусловно, могли бы создать поведение ОО и реализовать его с помощью сообщений, а затем получить method_missing, вызываемый объект не знает, что я пытался что-либо предпринять, поэтому он не может его интерпретировать .

...