2011-10-25 39 views
2

我目前正在學習編碼Erlang。我在芝加哥老闆之上有一個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

對不起,但element()函數做什麼?我對此很陌生。 :) –

回答

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

這比使用'proplist'好,因爲你只能通過列表一次。 – rvirding

0

不幸的是我不能希內克的回答發表評論,但作爲二郎新手,我的第一個猜測會一直去的東西沿着線:

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

你真的不能避免NewTodo分配

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())}]}.