首页 > 解决方案 > 在 Elixir 中,当 lambda 处于闭包中时,如何将 lambda 提取到命名函数?

问题描述

我有以下关闭:

  def get!(Item, id) do
    Enum.find(
      @items,
      fn(item) -> item.id == id end
    )
  end

由于我认为这看起来很难看且难以阅读,因此我想给它起一个名字,例如:

  def get!(Item, id) do
    defp has_target_id?(item), do: item.id = id
    Enum.find(@items, has_target_id?/1)
  end

不幸的是,这会导致:

== Compilation error in file lib/auction/fake_repo.ex ==
** (ArgumentError) cannot invoke defp/2 inside function/macro
    (elixir) lib/kernel.ex:5238: Kernel.assert_no_function_scope/3
    (elixir) lib/kernel.ex:4155: Kernel.define/4
    (elixir) expanding macro: Kernel.defp/2
    lib/auction/fake_repo.ex:28: Auction.FakeRepo.get!/2

假设有可能,这样做的正确方法是什么?

标签: functionlambdaclosureselixirextract

解决方案


您发布的代码有大量的语法错误/故障。我建议你从习惯语法开始,而不是试图通过发明没有人使用的东西来让 Elixir 变得更好。

这是执行您想要的正确版本。这个任务可以用一个匿名函数来完成,尽管我几乎看不出有什么理由让一个看起来很完美的惯用 Elixir 看起来很丑。

defmodule Foo do
  @items [%{id: 1}, %{id: 2}, %{id: 3}]
  def get!(id) do
    has_target_id? = fn item -> item.id == id end
    Enum.find(@items, has_target_id?)
  end
end

Foo.get! 1
#⇒ %{id: 1}
Foo.get! 4
#⇒ nil

推荐阅读