`with` tweak feature request - first clause on new line

I :heart: the with statement. I use it all the time, especially now that you can pattern match on the errors. Would it be possible to tweak the syntax to allow the first clause to be either on the same line as with (as it currently is) or on the following line?

Using the latter, the first statement gets the same visual weight as the proceeding ones, and more importantly, I can comment each step more easily (when self-documenting code is not quite enough).

with 
  # comment 1
  {:ok, x} <- foo(),
  # comment 2
  {:ok, y} <- bar()
  ...

would be equivalent to…

# comment 1
with {:ok, x} <- foo(),
  # comment 2
  {:ok, y} <- bar()
  ...

That would make with something special, different from everything else in the language. If you have a construct like with, foo, bar on a line on its own, it will be a variable or a function call. You need to use parentheses or add a \ at the end. I don’t believe we should add a special case.

1 Like

Putting the \ after it works perfectly - I should have known there was already a way to do it! :smile:

:ok =
  with \
  :ok <- foo(:ok),
  :ok <- bar(:ok) do
    :ok
  end
1 Like

I had been using the backslash method, and it worked in testing - but I hadn’t added the comment on the next line yet! When I did add a comment on the proceeding line, it didn’t compile and I had a heck of a time figuring out that the with \ method doesn’t like comments on the following line!

So the following is valid:

test "with, comma-do, newline, backslash" do
  :ok =
    with \
      :ok <- :ok,
      :ok <- :ok,
      do: :ok
end

But adding a comment invalidates the syntax:

# Doesn't compile
test "with, comma-do, newline, backslash, comments" do
  :ok =
    with \
      # Comment here <<<< Won't compile because of this line
      :ok <- :ok,
      :ok <- :ok,
      do: :ok
end

Fortunately, your answer pointed me to the solution using parentheses, but it was tricky (for me :wink: ) to get them to work with a do-else-end block. Here is the working final product:

test "with, do block, newline, parens, comments, else" do
  :ok =
    with(
      # Comment here
      :ok <- :ok,
      :ok <- :ok) do
      :ok
    else
      error -> :error
    end
end

Notice that the close paren goes before the do clause. I’ve uploaded a GitHub gist with the various syntaxes tried.

@josevalim I’m sure you and many others are aware of the with syntax nuances, but I am posting this to help anyone else who wants to combine the awesomeness of comments with the awesomeness of with. :smile: Thanks again for your help.

Congratulations, you find a parser bug! We have (hopefully) only a few of those left. :slight_smile: Could you please open up an issue so we fix this in the next release? Thank you!

4 Likes

I had no idea…I had thought it was a syntax thing! :laughing:

Done! :thumbsup: