Cannot use System.cmd inside a with

I’m trying to do something similar to this,

with {output, 0} <- System.cmd("git", ["reset"]) do
  #do something
end

but elixir gives me an error:

the function “cmd” cannot handle clauses with the → operator because it is not a macro. Please make sure you are invoking the proper name and that it is a macro

Is there anyway around this?

I can run this code without any problems.

with {output, 0} <- System.cmd("git", ["version"]) do
  IO.inspect(output)
end

or

iex(1)> with {output, 0} <- System.cmd("git", ["version"]), do: IO.inspect(output)
"git version 2.17.1\n"
"git version 2.17.1\n"
iex(2)>

Maybe your can send some more infos, so someone can help you a little bit more.

2 Likes

The error you pasted seems more related to improper use of cmd inside a -> clause (not <-) in pattern matching than to the with. Maybe you have an else clause using System.cmd on the wrong side?

The example you pasted here works just fine.

1 Like

Expanding on what I posted before, most likely this is a problem with parentheses and/or precedence. The example you posted works fine, but if you misplace parentheses, making Elixir believe that the do ... else ... end belongs to the System.cmd rather than to the with clause you get that error:

# WRONG, this causes the error you see
with {output, 0} <- (System.cmd("echo", ["hi"]) do
else
  _ -> nil
end)

# ** (CompileError) iex:7: the function "cmd" cannot handle clauses with the -> operator because it is not a macro. Please make sure you are invoking the proper name and that it is a # macro
#     (stdlib) lists.erl:1354: :lists.mapfoldl/3
2 Likes

Oh interesting! Yes, I am using an else but didn’t think it was related to the error!

      {output, 0} <- System.cmd("git", ["reset"]) do
          #something
      else
        {error, exit_code} ->
           #something else
      end

What’s the correct way to use parenthesis in this case?

The with has to be on the same line as your first clause. For the rest, what you wrote looks good and works well:

# This works well:
with {output, 0} <- System.cmd("echo", ["hi"]) do
  output
else
  _ -> nil
end

If you can paste your actual code someone can probably point you to the actual problem.

2 Likes

Oh wow! I didn’t think white space was that important in elixir. TIL. Thanks for the help.

1 Like

Only for if and when (I think; haven’t checked for case and cond). Their first argument has to be on the same line (or you put \ after the keyword and put the first argument on the next line).

EDIT: As was said, this indeed applies to all function calls without parentheses.

1 Like

This is true for any function call without parenthesis. The first argument and the comma (or equivalent keywords) have to be on the same line as the function name.

3 Likes