# How to write a recursive macro?

**URL:** https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652
**Category:** General Usage
**Created:** [July 22, 2022, 8:12pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652 "2022-07-22T20:12:56Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)
#### Post date: [July 22, 2022, 8:12pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652/1 "2022-07-22T20:12:56Z")

</div>

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

```julia
@or expr1 expr2 expr3 expr4

```

expands into

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

```

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

```julia
@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?

---

<div class="post-metadata">

### Author: ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)
#### Post date: [July 22, 2022, 8:38pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652/2 "2022-07-22T20:38:40Z")

</div>

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

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

```

```julia
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)

```

---

<div class="post-metadata">

### Author: ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)
#### Post date: [July 22, 2022, 8:44pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652/3 "2022-07-22T20:44:44Z")

</div>

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](https://stackoverflow.com/a/24843965/3623956) in Lisp.

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [July 22, 2022, 8:54pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652/4 "2022-07-22T20:54:45Z")

</div>

Like this?

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

```

```julia
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 🙂

---

<div class="post-metadata">

### Author: ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)
#### Post date: [July 22, 2022, 9:08pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652/5 "2022-07-22T21:08:06Z")

</div>

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

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.

---

<div class="post-metadata">

### Author: ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)
#### Post date: [July 22, 2022, 9:42pm UTC](https://discourse.julialang.org/t/how-to-write-a-recursive-macro/84652/6 "2022-07-22T21:42:39Z")

</div>

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

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

```
