2015-10-05 58 views
0

在編程鳳凰例如功能,第3章,沒有與下面的代碼硬編碼的回購例如:重寫編程使用管道

defmodule Rumbl.Repo do 
    @moduledoc """ 
    In memory repository. 
    """ 

    def all(Rumbl.User) do 
    [%Rumbl.User{id: "1", name: "José", username: "josevalim", password: "elixir"}, 
    %Rumbl.User{id: "2", name: "Bruce", username: "redrapids", password: "7langs"}, 
    %Rumbl.User{id: "3", name: "Chris", username: "chrismccord", password: "phx"}] 
    end 

    def all(_module), do: [] 

    def get(module, id) do 
    Enum.find all(module), fn map -> map.id == id end 
    end 

    def get_by(module, params) do 
    Enum.find all(module), fn map -> 
     Enum.all?(params, fn {key, val} -> Map.get(map, key) == val end) 
    end 
    end 
end 

使用的管道,我似乎更容易理解的方式改寫了get/2

 
    def get(module, id) do 
    all(module) 
    |> Enum.find fn map -> map.id == id end 
    end 

有沒有簡單的方法可以做到get_by/2

回答

2

,如果你願意,你可以這樣做:

def get_by(module, params) do 
    module 
    |> all() 
    |> Enum.find(fn map -> 
    Enum.all?(params, fn {key, val} -> Map.get(map, key) == val end) 
    end) 
end 
+0

謝謝,克里斯。我想我的問題更多地是關於如何使用管道來「解開」嵌套的Enum.find,Enum.all?和Map.get :) – gusaiani

+0

然後,一個單獨的功能,就像Proctor所說的那樣。 –

3

我的想法是,在這種情況下,清晰度會更容易實現,而不是由管道運營商本身,而是兩個不同的給予描述性名稱函數傳遞給不同的Enum函數,而不是使用匿名函數語法。

def get_by(module, params) do 
    Enum.find all(module), is_superset_of?(params) 
end 

defp is_superset_of?(key_value_pairs) do 
    fn map -> Enum.all?(key_value_pairs, key_value_pair_in?(map)) end 
end 

defp key_value_pair_in?(map) do 
    fn {key, value} -> Map.get(map, key) == value end 
end 

這是通過一個事實,即函數可以返回功能,並關閉了傳遞的值的優勢來完成。這使我們能夠提供一個名稱,表示先前的功能,這是匿名(未命名的函數)並內聯以利用關閉所需值的能力。

我們現在能夠捕捉到封閉的值,但同時增加了我們試圖完成的表現力。

所有這一切,假設我也準確地解釋了匿名函數的意圖。 ;)

+0

謝謝普羅克特。 我同意它使事情更容易理解。 小細節:'defp's需要函數名和參數後的'do'。 再次感謝您的幫助。 – gusaiani

+0

謝謝,這樣做沒有語法突出顯示,_和_ syntim在vim中運行。 :o – Proctor