我该如何优化呢?

时间:2011-10-25 08:59:16

标签: optimization erlang chicagoboss

我正在学习编写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应用程序,我可以查看。

3 个答案:

答案 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调用。这将破坏以前版本的改进。)

PS:如果你认为我是微优化狂,你是对的,所以我会用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())}]}.