weird "if" behaviour in macro's "quote"

306 views
Skip to first unread message

Serge Smetana

unread,
Dec 20, 2015, 9:47:45 AM12/20/15
to elixir-lang-talk
Hello all,

Can someone explain me what's wrong with this code?

test.exs:
defmodule Test do
  defmacro test
({:==, _, [left, right]} = _) do
    quote
do
      left
= unquote(left)
      right
= unquote(right)
     
if left == right do
        IO
.puts "Equal!"
     
else
        IO
.puts "Not Equal!"
     
end
   
end
 
end


 
def run do
    test
1 == 1
    test
1 == 2
 
end
end


Test.run

When I run it I get guards and clause warnings

~>elixir test.exs
test
.exs:15: warning: this clause cannot match because a previous clause at line 15 always matches
test
.exs:16: warning: this check/guard will always yield the same result
Equal!
Not Equal!

If I rewrite "if" in quote to "case" all works fine

test1.exs
defmodule Test do
  defmacro test
({:==, _, [left, right]} = _) do
    quote
do
      left
= unquote(left)
      right
= unquote(right)
     
case (left == right) do
       
true ->
          IO
.puts "Equal!"
        _
->
          IO
.puts "Not Equal!"
     
end
   
end
 
end


 
def run do
    test
1 == 1
    test
1 == 2
 
end
end


Test.run

Result

>elixir test1.exs
Equal!
Not Equal!


José Valim

unread,
Dec 20, 2015, 4:14:18 PM12/20/15
to elixir-l...@googlegroups.com
The compiler tries to warn on cases where things will be obviously always the same or dead clauses. It is a best effort thing, so those warnings are not guaranteed. Therefore what is happening is that the compiler is seeing those cases:

      if 1 == 1 do
        # Always true
      else
        # Never invoked
      end


and:

      if 1 == 2 do
        # Never true
      else
        # Always invoked
      end

And therefore warning on it. The other cases the compiler can't see in this version but may as well see in the future.



José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/d3669fc9-ba7b-40f6-b597-849590c2326f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

hen...@nyh.se

unread,
Dec 21, 2015, 5:52:41 AM12/21/15
to elixir-lang-talk, jose....@plataformatec.com.br
A way to avoid those warnings, then, could be to do the comparison at compile time and have the macro only produce the "IO.puts …" bit. That should also be slightly faster at runtime.

Serge Smetana

unread,
Dec 21, 2015, 12:56:17 PM12/21/15
to elixir-lang-talk, jose....@plataformatec.com.br
Got it. Thank you.
Reply all
Reply to author
Forward
0 new messages