Elixir的OO风格论证?

时间:2014-03-10 18:27:29

标签: javascript oop erlang arguments elixir

如何以类似OO的方式传递Elixir中的self参数?

例如,我用垃圾收集编写了这个Erlang Javascript like对象:

-module(o).

-export([n/0, g/2, s/3, d/1]).

-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(state, {dictionary=dict:new()}).

-define(SERVER, ?MODULE).

-on_load(deps/0).

deps() ->
    AS = fun(Mod) ->
        try application:start(Mod) catch _Type:_What -> ok end
    end,
    [AS(Mod) || Mod <- [sasl, lager, resource]],
    ok.

n() ->
    case gen_server:start(?MODULE, {}, []) of
        {ok, Pid} ->
            Res = resource:notify_when_destroyed(Pid, {timeout, Pid}),
            {?MODULE, {Res, Pid}};
        Other ->
            Other
    end.

g(Key, {?MODULE, {_Res, Pid}}) ->
    gen_server:call(Pid, {g, Key}).

s(Key, Val, {?MODULE, {_Res, Pid}}) ->
    gen_server:cast(Pid, {s, Key, Val}).

d({?MODULE, {_Res, Pid}}) ->
    gen_server:cast(Pid, stop).

%% @private
init({}) ->
    {ok, #state{}}.

%% @private
handle_call({g, Key}, _From, State = #state{dictionary=Dict}) ->
    {reply, case dict:find(Key, Dict) of {ok, Val} -> Val; error -> error end, State};
handle_call(Request, _From, State) ->
    lager:info("handle_call discarded request: ~p", [Request]),
    {reply, {error, unknown_call}, State}.

%% @private
handle_cast({s, Key, Value}, State = #state{dictionary=Dict}) ->
    {noreply, State#state{dictionary=dict:store(Key, Value, Dict)}};
handle_cast(stop, State) ->
    {stop, normal, State};
handle_cast(Msg, State) ->
    lager:info("handle_cast discarded message: ~p", [Msg]),
    {noreply, State}.

%% @private
handle_info({timeout, Pid}, State) ->
    d({?MODULE, {res, Pid}}),
    lager:info("Garbage collection of object ~p", [Pid]),
    {noreply, State};
handle_info(Info, State) ->
    lager:info("handle_info discarded message: ~p", [Info]),
    {noreply, State}.

%% @private
terminate(_Reason, _State) ->
    ok.

%% @private
code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

注意:我使用https://github.com/tonyrog/resource.git进行资源收集。

1> l(o).
... LOGS ...
{module,o}
2> O = o:n().
{o,{{resource,140524043665312,<<>>},<0.58.0>}}
3> O:s(a, b).
ok
4> O:g(a).
b
6> O:s(hello, fun() -> io:format("Hello World~n") end). 
ok
7> (O:g(hello))().
Hello World
ok

1 个答案:

答案 0 :(得分:2)

据我所知,在Elixir中以这种方式调用模块是不可能的。您必须为所有调用显式传递self参数。所以把你的Erlang例子带到Elixir,看起来像是:

iex> o = O.n()
{O, {{:resource, 140524043665312, <<>>}, <0.58.0>}}
iex> O.s(:a, :b, o)
:ok
iex> O.g(:a, o)
:b
...

其他人可以在这里找到并纠正我,但是我没有看到你在我见过的任何Elixir代码中所展示的类似OO的访问。