Adam Millerchip
Adam Millerchip

Reputation: 23091

Using pipe on next line in iex (syntax error before: '|>')

In chains of pipes in Elixir, it's standard to place the pipe at the beginning on the line:

1
|> IO.inspect(label: "initial value")
|> Kernel.+(1)
|> IO.inspect(label: "plus one")
|> Kernel.*(2)
|> IO.inspect(label: "times two")
|> Integer.to_string(2)
|> IO.inspect(label: "in binary")

However, when I try to do this in IEx, the following happens:

iex(1)> 1
1
iex(2)> |> IO.inspect(label: "initial value")
** (SyntaxError) iex:2:1: syntax error before: '|>'

It is possible to workaround by moving the pipe operator to the end of the line:

iex(1)> 1 |>
...(1)> IO.inspect(label: "initial value") |>
...(1)> Kernel.+(1) |>
...(1)> IO.inspect(label: "plus one") |>
...(1)> Kernel.*(2) |>
...(1)> IO.inspect(label: "times two") |>
...(1)> Integer.to_string(2) |>
...(1)> IO.inspect(label: "in binary")
initial value: 1
plus one: 2
times two: 4
in binary: "100"
"100"

But that's tedious and unidiomatic. Is it possible to use pipes in IEx with the pipe on the next line, like we do in source files?

Upvotes: 4

Views: 1050

Answers (1)

Adam Millerchip
Adam Millerchip

Reputation: 23091

This is supported in recent versions:

Interactive Elixir (1.12.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [1, [2], 3]
[1, [2], 3]
iex(2)> |> List.flatten()
[1, 2, 3]

Prior to Elixir 1.12, it was not possible to copy-paste multi-line pipes like your example verbatim into IEx. This was a symptom of the fact that code in IEx is evaluated line-by-line.

The simplest workaround is to wrap the expression in parentheses:

iex(1)> (
...(1)>     1
...(1)>     |> IO.inspect(label: "initial value")
...(1)>     |> Kernel.+(1)
...(1)>     |> IO.inspect(label: "plus one")
...(1)>     |> Kernel.*(2)
...(1)>     |> IO.inspect(label: "times two")
...(1)>     |> Integer.to_string(2)
...(1)>     |> IO.inspect(label: "in binary")
...(1)> )
initial value: 1
plus one: 2
times two: 4
in binary: "100"
"100"

You can also escape the newlines:

iex(1)> 1 \
...(1)> |> IO.inspect(label: "initial value") \
...(1)> |> Kernel.+(1) \
...(1)> |> IO.inspect(label: "plus one") \
...(1)> |> Kernel.*(2) \
...(1)> |> IO.inspect(label: "times two") \
...(1)> |> Integer.to_string(2) \
...(1)> |> IO.inspect(label: "in binary") \
...(1)>
initial value: 1
plus one: 2
times two: 4
in binary: "100"
"100"

Upvotes: 7

Related Questions