我正在学习编写Erlang代码。我在Chicago Boss上面有一个Web应用程序。 我有一个名为Todo的模型,我想作为REST API提供CRUD操作。
在我的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())}]}.
如何优化此代码片段?或者这已经是最好的了?
是否有一些“更智能”的方法将proplist的键更改为原子键?像这样:
[{"subject", "Foo"}] -> [{subject, "Foo"}].
我还发现分配一个Todo变量然后有一个NewTodo有点乏味。可悲的是,我无法在github上找到一些很好的例子Erlang Chicago Boss应用程序,我可以查看。
答案 0 :(得分:1)
你总能做到这样的事情:
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
调用。这将破坏以前版本的改进。)
lists:reverse/1
取代lists:reverse/2
来直接使用BIF并节省更多时间; - )
答案 1 :(得分:0)
不幸的是我不能对Hynek的答案发表评论,但作为Erlang的新手,我的第一个猜测就是去做一些事情:
lists:map(fun({A, B}) -> {list_to_atom(A), B} end, [X || {Y, Z}=X <- List, is_list(Y)]).
你无法真正避免使用NewTodo
答案 2 :(得分:0)
怎么样
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())}]}.