使用管道

时间:2015-10-05 00:23:22

标签: elixir phoenix-framework

在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执行相同的操作?

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