dokuzbir

dokuzbir

Need help about quote and unquote

This code is from metaprograming elixir book. I dont understand when should use unquote. In first function there is no unqote to execute expression but in second function there is unquote why ?

defmodule ControlFlow do
 # Why there is no unquote here ?
  defmacro my_if(expr, do: if_block), do: if(expr, do: if_block, else: nil) 
 
# Why there is unquote here ?
  defmacro my_if(expr, do: if_block, else: else_block) do
    quote do
      case unquote(expr) do
        result when result in [false, nil] -> unquote(else_block)
        _ -> unquote(if_block)
      end
    end
  end
end

First 8 of 8 Posts Switch mode

gregvaughn

gregvaughn

I suspect there’s a typo there. The first my_if clause should be:

defmacro my_if(expr, do: if_block), do: my_if(expr, do: if_block, else: nil)

so it delegates to the 2nd clause

dokuzbir

dokuzbir OP

But it works when it is if.

gregvaughn

gregvaughn

It’s calling Kernel.if/2 which is a macro that handles the quoting itself. But if you’re going to rely on Kernel.if then why write my_if? That’s why I think it’s a typo.

dokuzbir

dokuzbir OP

So in a macro we can use another macro without quote. Thanks i got it

dokuzbir

dokuzbir OP

I tried a smilar approach for while as first if function, but my_second_while function freezes iex. my_while function is working as expected

defmodule Loop do
	defmacro my_while(expression, do: block) do
		quote do
			for _ <- Stream.cycle([:ok]) do
				if unquote(expression) do
					unquote(block)
				else
				# break out of loop
				end
			end
		end
	end

    #Same as first if function 
	defmacro my_second_while(expression, do: block) do
		my_while(expression, do: block)
	end
end

iex

require Loop
Loop.my_second_while true do
IO.puts "looping!"
end
OvermindDL1

OvermindDL1

Should be:

quote(do: my_while(expression, do: block))

Also, your Stream.cycle bit is not ever going to end, it will loop forever?

dokuzbir

dokuzbir OP

Yes i guess so but why first my_if function works without unquote? what is difference? That example from book yes never ends

aethereus

aethereus

Your no-quote version of my_if does not work. I tested it with the following code:

ControlFlow.my_if 1 > 2, do: IO.puts("This should not be printed.")

And I saw that the sentence “This should not be printed.” is actually printed. This is because when you pass 1 > 2 to expr, it gets automatically quoted (becomes AST), and the AST is {:>, [context: Elixir, import: Kernel], [1, 2]} and is not false or nil, so the test of if(expr, ...) passes, and the if_block (which is also an AST) gets returned by the macro my_if.

If you test it with

ControlFlow.my_if false, do: IO.puts("This should not be printed.")

You get the correct behavior by accident because false is an atom, and atoms are “Elixir literals” that have exactly the same form in code and in AST.

— All posts loaded —

Where Next?

Trending in Questions Top

jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
silverdr
Using Phoenix.LiveView.TagEngine as an EEx.Engine is deprecated! To compile HEEx, use Phoenix.LiveView.TagEngine.compile/2 instead. Sta...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
michallepicki
I am using Oban and occasionally, shortly after a deployment, a handful of jobs can fail because of dependency on other parts of the syst...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement