如何以类似 OO 的方式在 Elixir 中传递 self 参数?
例如,我编写了这个带有垃圾收集的 Erlang Javascript 对象:
-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