Как я могу оптимизировать это?
В настоящее время я учусь кодировать Erlang. У меня есть веб-приложение поверх Chicago Boss. У меня есть модель под названием Todo, и я хотел бы предложить операции CRUD над ней в качестве REST API.
В моем методе PUT у меня есть этот код:
index('PUT', [Id]) ->
Todo = boss_db:find(Id),
Body = element(2, mochijson:decode(Req:request_body())),
%% Set the new values
NewTodo = Todo:attributes([
{subject, proplists:get_value("subject", Body)},
{done, proplists:get_value("done", Body)}
])
,
{json, [{todo, element(2, NewTodo:save())}]}.
Как я могу оптимизировать этот фрагмент кода? Или это уже лучшее из возможных?
Есть ли какой-нибудь "умный" способ изменить ключи проплиста на ключи атома? Как это:
[{"subject", "Foo"}] -> [{subject, "Foo"}].
Я также нахожу утомительным присваивать переменную Todo и затем иметь NewTodo. К сожалению, я не могу найти хороший пример приложений Erlang Chicago Boss на github, которые я могу проверить.
3 ответа
Вы всегда можете сделать что-то вроде этого:
t([{"subject", V}|T]) -> [{subject, V}|t(T)];
t([{"done" , V}|T]) -> [{done, V}|t(T)];
t([_ |T]) -> t(T) ; % optional garbage ignoring clause
t([]) -> [].
Но я сомневаюсь, это будет значительное улучшение скорости в вашем случае.
Может быть, вы сможете выжать последний бит из этого:
-compile({inline, [t/1]}).
t(L) -> t(L, []).
t([{"subject", V}|T], A) -> t(T, [{subject, V}|A]);
t([{"done" , V}|T], A) -> t(T, [{done, V}|A]);
t([_ |T], A) -> t(T, A); % optional garbage ignoring clause
t([], A) -> A.
Который стоит только для бенчмарков;-) (заметки нет lists:reverse/1
позвоните в последнем пункте. Было бы испортить улучшение от предыдущей версии.)
PS: Если вы думаете, что я фанат микро-оптимизации, вы правы, поэтому я бы заменил lists:reverse/1
позвонить с lists:reverse/2
использовать BIF напрямую и сэкономить немного времени;-)
К сожалению, я не могу комментировать ответ Хайнека, но, как новичок Эрланга, мое первое предположение было бы пойти на что-то вроде:
lists:map(fun({A, B}) -> {list_to_atom(A), B} end, [X || {Y, Z}=X <- List, is_list(Y)]).
Вы не можете действительно избежать назначения NewTodo
Как насчет
index('PUT', [Id]) ->
Body = element(2, mochijson:decode(Req:request_body())),
OldTodo = boss_db:find(Id),
NewTodo = OldTodo:attributes([ {list_to_atom(A),B} || {A,B}<-Body ]),
{json, [{todo, element(2, NewTodo:save())}]}.