How to write a one liner for comprehension

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

Got it. Thanks again.