There are no “methods defined on objects” in Elixir. Modules have functions. To call a function, one should call it as String.upcase
:
iex> id = & &1
iex> "Hello" |> id.() |> String.upcase()
#⇒ "HELLO"
If you insist on calling upcase
without using it’s fully-qualified name, do import String, only: [upcase: 1]
upfront:
iex> import String, only: [upcase: 1]
iex> "Hello" |> id.() |> upcase()
#⇒ "HELLO"
Anonymous functions can not be used in the pipe chain since they are literally anonymous. Binding the anonymous function to the local variable does not make it “pipeable,” and the explicit function call is needed. The same way one pipes to the actual call of the String.upcase/1
, not to “variable it’s bound to.” The following won’t work without an explicit call with .()
too:
iex> id = &String.upcase/1
iex> "hello" |> id
while this works:
iex> id = &String.upcase/1
iex> "hello" |> id.()
One might always see the difference by checking the respective 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}]}, [], []}]}