# How to write a recursive macro?

I came across some online posts about implementing short-circuiting logical operators as macros in Lisp, and I’m wondering how to do the same in Julia. I’m trying to write a vararg macro `@or` such that

``````@or expr1 expr2 expr3 expr4
``````

expands into

``````if expr1
true
else
@or expr2 expr3 expr4
end
``````

The recursion should end when there is only one argument, i.e.

``````@or expr1
``````

should expand into simply `expr1`.

I made some attempts but got confused about how to interpolate vararg tuples in `quote` expressions. Any ideas?

This is not recursive, however it seems to do what you want.

``````ior(x,y) = x || y
macro or(xs...)
:(foldl(ior, \$xs, init=false))
end
``````
``````julia> @or(false), @or(true)
(false, true)

julia> @or(false, false), @or(true, true)
(false, true)

julia> @or(true, false), @or(false,true)
(true, true)
``````

Thanks, but I was actually trying to avoid the built-in `||` operator and re-implement it using only the if-else clause, just for fun, following this Stack Overflow Post in Lisp.

Like this?

``````macro or(args...)
length(args) == 1 && return only(args)
quote
if \$(esc(args))
true
else
@or \$(args[2:end]...)
end
end
end
``````
``````julia> @or 1 == 2 1 == 3 1 == 1
true

julia> @macroexpand @or 1 == 2 1 == 3 1 == 1
quote
#= Untitled-2:150 =#
if 1 == 2
#= Untitled-2:151 =#
true
else
#= Untitled-2:153 =#
begin
#= Untitled-2:150 =#
if 1 == 3
#= Untitled-2:151 =#
true
else
#= Untitled-2:153 =#
1 == 1
end
end
end
end
``````

Probably the escaping isn’t quite right 1 Like

That works! A little glitch is that I tried to add `esc` to your `args[2:end]` but that breaks the interpolation. I’ll be very interested if someone knows how to do this.

OK, here’s a simple modification of @jules’s code to impose hygiene.

``````macro or(args...)
args_esc = esc.(args)
length(args_esc) == 1 && return only(args_esc)
quote
if \$(args_esc)
true
else
@or \$(args_esc[2:end]...)
end
end
end
``````