Вызов Функции Через Кортеж

Не так давно я наткнулся на интересную возможность в Эрланге.

Если вместо имени модуля при вызове функции передать кортеж, где первым элементом является имя модуля, то будет вызвана функция Арность на единицу больше, чем вызванная, и последний аргумент будет тем же кортежем.

Пример:

  
  
  
  
  
  
   

-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

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.