2

我目前正在学习编写 Erlang 代码。我在 Chicago Boss 之上有一个 Web 应用程序。我有一个名为 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())}]}.

如何优化此代码片段?或者这已经是最好的了?

是否有一些“更智能”的方法可以将 proplist 的键更改为原子键?像这样:

[{"subject", "Foo"}] -> [{subject, "Foo"}].

我还发现分配一个 Todo 变量然后拥有一个 NewTodo 有点乏味。遗憾的是,我在 github 上找不到一些可以查看的好示例 Erlang Chicago Boss 应用程序。

4

3 回答 3

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/1calllists:reverse/2直接使用 BIF 并节省更多时间;-)

于 2011-10-25T09:57:22.237 回答
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())}]}.
于 2012-12-26T04:57:37.313 回答
0

不幸的是,我无法评论 Hynek 的回答,但作为 Erlang 新手,我的第一个猜测是:

lists:map(fun({A, B}) -> {list_to_atom(A), B} end, [X || {Y, Z}=X <- List, is_list(Y)]).

你无法真正避免 NewTodo 分配

于 2012-12-26T04:42:50.003 回答