Erlang:有没有办法从我的模块中导出其他模块的导出?

发布于 2024-10-18 07:47:10 字数 105 浏览 2 评论 0原文

我正在为 webmachine 编写一些资源,它们共享许多相同的功能。所以我想知道是否可以在单独的模块中编写常用函数,然后以某种方式包含它,并让资源自动导出其导出(而不必从每个资源显式导出它们)。

I'm writing several resources for webmachine that share lots of same functions. So I'm wondering if it's possible to write the common functions in a separate module, then somehow include it, and have its exports automatically exported by the resource (without having to export them from every resource explicitly).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黎歌 2024-10-25 07:47:10

我们有一个包装器模块,它实现所有 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}}.

这在我们的项目中效果很好,其中所有资源共享一些通用逻辑(在这样的包装器模块中实现)。虽然还没有对性能进行太多的基准测试,但开销应该相当小(一次字典查找和一次额外的模块调用,再加上一些记录争论)。

We have a wrapper module that implements all Webgear callbacks and transfers them to the real implementation module if they are implemented there. That module can have special implementations for certain parts or even enable new callbacks in the modules using it. Basically that module is a wrapper resource for all your other resources.

First, your dispatch map would look as follows:

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

To do this, you need to discover what callbacks your actual implementation module implements:

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

This will initialize a basic Webgear resource that has information about the real callback module in its state.

Then, for every callback to the wrapper resource (which you must implement if you want your implementation modules to be able to use then), you would see if that function was implemented and handle it there, using this function:

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.

The call/4 function is, for example, used like this in the wrapper module:

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

This works well in our project where all resources share some common logic (implemented in such a wrapper module). Haven't benchmarked the performance very much though, but the overhead should be fairly small (one dict lookup and one extra module call, plus some record wrangling).

趁年轻赶紧闹 2024-10-25 07:47:10

是的,您可以使用混合器库,https://github.com/opscode/mixer 它是一个编译器解析转换将完全按照您的要求进行。我到处都用它来进行网络机器回调

Yes you can use the mixer library, https://github.com/opscode/mixer it is a compiler parse transform that will do exactly what you want. I use it all over the place for webmachine callbacks

少年亿悲伤 2024-10-25 07:47:10

不,这是不可能的。我所做的是将我的应用程序所需的所有回调实现到通用函数。另一种方法是修补 webmachine 以从函数中获取 cb,而不是通过查看导出。

No,it is not possible. What I did was to implement all the callbacks needed by my app to the generic function. Another way would be to patch webmachine to fetch the cb's from a function instead of by looking at exports.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文