为什么Enum.filter不能与字典参数一起使用?

时间:2019-08-16 15:19:14

标签: elixir

我正在使用Enum.filter/2过滤列表。

我已经简化了代码,使其几乎没有必要隔离出正在发生的事情,但是我不知道它出了什么问题。

代码如下:

defmodule Servy.Reducer do
   alias Servy.Wildthings

   def index(%{} = bear_filter) do
      Wildthings.list_bears()
      |> Enum.filter(
         fn(bear) ->
          IO.inspect(bear_filter)
          case bear do 
             bear_filter -> true
                       _ -> false
               end
            end)
   end  
end

当我编译时,会收到这些警告,如果为true,则可以解释问题。我既不理解为什么bear_filter未使用,也不知道为什么_子句不可访问。

warning: variable "bear_filter" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/servy/reducer.ex:10: Servy.Reducer.index/1

warning: this clause cannot match because a previous clause at line 10 always matches
  lib/servy/reducer.ex:11

3 个答案:

答案 0 :(得分:2)

长生不老药允许变量反弹。因此,在您的案例表达式中,您拥有分支bear_filter -> true。这实际上是在创建一个新变量并始终匹配(这就是为什么它说它未被使用以及第二个分支不可达的原因)。如果要与传递给函数的bear_filter相匹配,则需要添加pin operator。因此,您需要将该行更改为^bear_filter -> true

答案 1 :(得分:1)

对于这种特殊情况,您最好使用Kernel.match?/2宏:

for ^bear_filter <- Wildthings.list_bears(), do: bear_filter

Kernel.SpecialForms.for/1理解:

%{foo: 42}

这两种方法都立即表明您希望在这里发生一些神奇的事情。我很想您要通过match?/2这样的过滤器。我建议您直接使用Enum.filter(Wildthings.list_bears(), &match?(%{foo: _}, &1))

%{foo: _}

如果要将其包装到帮助器中,则需要一个宏来接受类似{{1}}的参数。

答案 2 :(得分:0)

bear_filter -> true

在第10行,您将bear_filter与参数bear进行模式匹配,然后在结果表达式中不使用它(true不包含bear_filter)。

由于_用于执行模式匹配,因此case无法访问。在这种情况下,bear_filter将与输入的任何值进行模式匹配,从而导致bear_filter -> true始终匹配并执行。