Не так давно я наткнулся на интересную возможность в Эрланге.
Если вместо имени модуля при вызове функции передать кортеж, где первым элементом является имя модуля, то будет вызвана функция Арность на единицу больше, чем вызванная, и последний аргумент будет тем же кортежем.
Пример:
Можно назвать так:-module(my_module).
-export([test/2]).
test(Arg1,{ЭMODULE,Arg2}) -> io:format("Arg1:~p~nArg2:~p~n",[Arg1,Arg2]).
my_module:test(1,{my_module,2}).
или так
{my_module,2}:test(1).
Как это можно применить?
Например, при создании абстрактных типов данных (моделей данных), где в кортеже (или, что удобнее, в записывать -e) все данные сохраняются.
-module(user).
-export([new/0,save/1]).
-export([name/1,set_name/1]).
-export([proplist/1]).
% record name must be same as module name. -record(user,{id,name}).
new() -> {ok,#user{}}.
name(#user{name=Name}) -> Name. set_name(NewName) -> {ok,State#user{name=NewName}}.
% … Some other code .
save(#user{id=undefined,name=Name} = State) -> % Create new object in db; % .
{ok,State}; save(#user{id=ID,name=Name} = State) -> % Update an object in database % .
{ok,State}; proplist(#user{id=ID,name=Name}) -> [{id,ID}, {name,Name}].
В результате получается тип пользователя, который довольно удобно использовать в коде: {ok,User} = user:new(),
{ok,User2} = User:set_name("SomeName"),
{ok,User3} = User2:save(),
UserName = User3:name().
В принципе идея понятна, но программирование в таком стиле — это не по-эрланговски, к тому же усложнена статическая проверка кода.
Диализатор .
Плюс этот код отличается от этого {ok,User} = user:new(),
{ok,User2} = user:set_name("SomeName",User),
{ok,User3} = user:save(User2),
UserName = user:name(User3).
только по количеству символов.
Вот почему Я не рекомендую использовать его это повсюду.
В своем проекте я использовал эту возможность только из-за возможности создания функции над абстрактным типом данных, зная интерфейс доступа к ней (например, в предыдущей модели функция используется как интерфейс пролист() ).
При разработке RESTful-сервиса очень удобно описывать ресурсы моделями, а по возвращении преобразовывать их в нужные типы, не зная, к какому конкретному модулю принадлежит эта модель.
to_json(Resource) ->
Proplist = Resource:proplist(),
Json = mochijson2_fork:encode({struct,[Proplist]}),
{ok,Json}.
to_xml(Resource) -> Proplist = Resource:proplist(), XML = SomeProplistToXmlGenerator(Proplist), {ok,XML}.
Теги: #erlang #Erlang/OTP
-
Босния И Герцеговина
19 Oct, 24 -
Год Жизни В Дании (Часть 1)
19 Oct, 24 -
Swype — Интересная Клавиатура Для Android
19 Oct, 24