使用管道运算符调用匿名函数

Jon*_*ion 0 elixir

我想知道为什么我们需要.()在使用管道运算符时添加,如果没有调用该函数并且只接收一个参数?

id = &(&1)

"Hello" |> id.() |> upcase # HELLO
Run Code Online (Sandbox Code Playgroud)

预期:

id = &(&1)

"Hello" |> id. |> upcase # "undefined function String.upcase/0"
Run Code Online (Sandbox Code Playgroud)

为什么不起作用?我想解释一下Elixir的行为方式.

Ale*_*kin 5

Elixir 中没有 "对象定义的方法".模块具有功能.要调用函数,应将其称为String.upcase:

iex> id = & &1
iex> "Hello" |> id.() |> String.upcase()
#? "HELLO"
Run Code Online (Sandbox Code Playgroud)

如果您坚持在upcase不使用完全限定名称的情况下致电,请import String, only: [upcase: 1]事先做好:

iex> import String, only: [upcase: 1]
iex> "Hello" |> id.() |> upcase()
#? "HELLO"
Run Code Online (Sandbox Code Playgroud)

匿名函数不能在管道链中使用,因为它们字面上是匿名的.将匿名函数绑定到局部变量不会使其"可管理",并且需要显式函数调用.同样的方式管道实际调用,而String.upcase/1不是"变量绑定."如果没有显式调用,以下将无法工作.():

iex> id = &String.upcase/1
iex> "hello" |> id
Run Code Online (Sandbox Code Playgroud)

虽然这有效:

iex> id = &String.upcase/1
iex> "hello" |> id.()
Run Code Online (Sandbox Code Playgroud)

人们可能总是通过检查相应的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}]}, [], []}]}
Run Code Online (Sandbox Code Playgroud)