markdev

markdev

Are macros lazily evaluated?

I am watching this talk by Jesse Anderson at ElixirConf about how macros work. He creates a macro (if statement), then contrasts it with a functional example.

Macro Version:

defmodule MyMacros do
  defmacro my_if(condition, do: do_clause, else: else_clause) do
    quote do
      case unquote(condition) do
        true -> unquote(do_clause)
        false -> unquote(else_clause)
      end
    end
  end
end

Function version:

defmodule MyFunctions do
  def my_if(condition, do: do_clause, else: else_clause) do
     case condition do
        true -> do_clause
        false -> else_clause
      end
   end
end

If you were to call my_if 1 + 2 == 3, do: "this", else: "that", you get the same result from either module. But if evaluation order matters in the do/else blocks, the behavior is different.

iex(17)> MyMacros.my_if 1 + 2 == 3, do: IO.puts("this"), else: IO.puts("that")
this
:ok
iex(18)> MyFunctions.my_if 1 + 2 == 3, do: IO.puts("this"), else: IO.puts("that")
this
that
:ok

Is this considered an example of lazy evaluation, or is this deferred evaluation typically described some other way?

Marked As Solved

tmbb

tmbb

Your macro isn’t perdorming any kind of evaluation, lazy or strict. The macro works because it expands into a case special form, which does allow you to pick branches. In a sense I guess the case macros is doing something that can be considered lazy evaluation.

But your if macro is not performing lazy evaluation. It’s just expanding into another syntax form.

Also Liked

blatyo

blatyo

Conduit Core Team

A macro is replaced with the AST that it returns. So, this:

MyMacros.my_if 1 + 2 == 3, do: IO.puts("this"), else: IO.puts("that")

Turns into this at compile time:

case 1 + 2 == 3 do
  true -> IO.puts("this")
  false -> IO.puts("that")
end

Like @tmbb said, case is lazy. Not the macro.

The function appears non-lazy, because the arguments have to be evaluated before they are passed to MyFunctions.my_if/2.

Where Next?

Popular in Questions Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
gonzofish
I’m currently trying to understand how to join three tables using Ecto. All the examples I’ve seen use 2, so maybe I’m just missing somet...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement