在Phoenix编程,第3章中,有一个带有以下代码的硬编码repo示例:
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
执行相同的操作?
答案 0 :(得分: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
这是通过利用函数可以返回函数并关闭传入的值这一事实来实现的。这允许我们为表示前一个匿名(未命名)函数和内联函数的函数命名。利用关闭所需值的能力。
我们现在能够捕捉到封闭的价值观,但同时也增加了我们想要实现的表现力。
所有这些,假设我确实准确地解释了匿名函数的意图。 ;)
答案 1 :(得分: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