I was under the assumption that
for x <- 1..4 , do: x
it is a one liner. But while trying out some code below, i saw this does not act as one line. Why is it so?
defmodule MyTest do
## test1 does not work. acts like ":rand.uniform |> Enum.sort"
## all other functions work as expected
def test1 do
for _ <- 1..4, do: :rand.uniform(6)
|> Enum.sort
end
def test2 do
(for _ <- 1..4, do: :rand.uniform(6))
|> Enum.sort
end
def test3 do
for _ <- 1..4 do
:rand.uniform(6)
end
|> Enum.sort
end
def test4 do
for( _ <- 1..4, do: :rand.uniform(6))
|> Enum.sort
end
end
Operator precedence. This allows things like:
def foo, do: :rand.uniform(6) |> to_string()
In all other cases you have explicitly marked where the :do
block is ending.
3 Likes
Thank you.
if i try just
for _ <- 1..4, [do: :rand.uniform(6)]
It works.
But the below code gives a compiler error!
def test5 do
for _ <- 1..4, [do: :rand.uniform(6)]
|> Enum.sort
end
** (CompileError) test.ex:23: missing :do option in "for"
for _ <- 1..4, [do: :rand.uniform(6)] |> Enum.sort
Do you see the ambiguity now?
What you need is
(for _ <- 1..4, do: :rand.uniform(6))
|> Enum.sort
3 Likes
Why are you doing this?
There is the correct syntax.
for _ <- 1..4, do: :rand.uniform(6)
for _ <- 1..4 do :rand.uniform(6) end
And you’re screwing it up and asking why it doesn’t work.
1 Like
Thank you.
I went by the below statement
“if our function body only spans one line, we can shorten it further with do:” Functions · Elixir School
thinking if i use “do:”, only whatever comes after the “do:” in that line only is accounted as part of the “do action”.
I understood my mistake now.
To understand what works and what does not in a single line for with “do:”
The root of the problem is the pipe operator. The parser wants to pipe your “do” body to the following call and the result can be the “do action”. But that’s not what you intend.
3 Likes