Эрланг: есть ли способ экспортировать экспорт некоторых других модулей из моего модуля? - PullRequest
3 голосов
/ 19 февраля 2011

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

Ответы [ 4 ]

3 голосов
/ 21 февраля 2011

У нас есть модуль-обертка, который реализует все обратные вызовы Webgear и передает их в реальный модуль реализации, если они реализованы там. Этот модуль может иметь специальные реализации для определенных частей или даже включать новые обратные вызовы в модулях, использующих его. По сути, этот модуль является ресурсом-оберткой для всех ваших других ресурсов.

Во-первых, ваша карта отправки будет выглядеть следующим образом:

[{"/some/path", webgear_wrapper, {actual_resource, ["Some", extra, "Args"]}}].

Для этого вам необходимо выяснить, какие обратные вызовы реализует ваш фактический модуль реализации:

-record(context, {module, context, exports}).

init({Mod, Args}) ->
    {ok, Context} = Mod:init(Args),
    {ok, #context{module = Mod, context = Context, exports = exports(Mod)}}.

exports(Mod) ->
    dict:from_list(Mod:module_info(exports)).

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

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

call(#context{module = Mod, context = Cxt, exports = Exports},
     Func, Req, Default) ->
    case dict:is_key(Func, Exports) of
        true  -> Mod:Func(Req, Cxt);
        false -> {Default, Req, Cxt}
    end.

Функция call/4, например, используется в модуле оболочки следующим образом:

malformed_request(Req, Cxt) ->
    % false here is the default value to return if the callback is missing
    {Res, NewReq, NewCxt} = call(Cxt, malformed_request, Req, false),
    % Now we must update the state accordingly
    {Res, NewReq, Cxt#context{context = NewCxt}}.

Это хорошо работает в нашем проекте, где все ресурсы имеют общую логику (реализованную в таком модуле-обертке). Хотя производительность не очень сильно оценивалась, но накладные расходы должны быть довольно небольшими (один анализ dict и один дополнительный вызов модуля, а также некоторые записи).

2 голосов
/ 20 февраля 2011

На самом деле это возможно, но только через недокументированную функцию. Модуль наследования.

1 голос
/ 09 сентября 2013

Да, вы можете использовать библиотеку микшера, https://github.com/opscode/mixer это преобразование синтаксического анализа, которое будет делать именно то, что вы хотите. Я использую это везде для обратных вызовов веб-машины

0 голосов
/ 19 февраля 2011

Нет, это невозможно.Я реализовал все обратные вызовы, необходимые моему приложению, для универсальной функции.Другим способом было бы исправление веб-машины для извлечения КБ из функции вместо просмотра экспорта

...