我想知道为什么我们需要在使用管道运算符时添加.()
,如果没有调用该函数并且只接收一个参数?
id = &(&1)
"Hello" |> id.() |> upcase # HELLO
预期:
id = &(&1)
"Hello" |> id. |> upcase # "undefined function String.upcase/0"
为什么它不起作用?我想解释一下Elixir的行为方式。
答案 0 :(得分:5)
Elixir中有对象上定义的 no “方法”。模块具有功能。要调用函数,应将其称为String.upcase
:
iex> id = & &1
iex> "Hello" |> id.() |> String.upcase()
#⇒ "HELLO"
如果您坚持在不使用完全限定名称的情况下致电upcase
,请事先import String, only: [upcase: 1]
:
iex> import String, only: [upcase: 1]
iex> "Hello" |> id.() |> upcase()
#⇒ "HELLO"
匿名函数不能在管道链中使用,因为它们字面上是匿名的。将匿名函数绑定到局部变量不会使其“可管理”,并且需要显式函数调用。同样的方法是管道String.upcase/1
的实际调用,而不是“变量绑定到。”如果没有.()
的显式调用,以下内容将无效:
iex> id = &String.upcase/1
iex> "hello" |> id
虽然这有效:
iex> id = &String.upcase/1
iex> "hello" |> id.()
人们可能总是通过检查相应的AST来看到差异:
iex> quote do: "hello" |> id
#⇒ {:|>, [context: Elixir, import: Kernel], ["hello", {:id, [], Elixir}]}
iex> quote do: "hello" |> id.()
#⇒ {:|>, [context: Elixir, import: Kernel],
# ["hello", {{:., [], [{:id, [], Elixir}]}, [], []}]}