# Problem with LFE macro

**URL:** <https://erlangforums.com/t/problem-with-lfe-macro/1039>\
**Category:** LFE Questions\
**Tags:** lfe-questions, lfe-user\
**Created:** [February 6, 2022, 2:33pm UTC](https://erlangforums.com/t/problem-with-lfe-macro/1039 "2022-02-06T14:33:06Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdbergmann](https://erlangforums.com/user_avatar/erlangforums.com/mdbergmann/32/1243_2.png) [@mdbergmann](https://erlangforums.com/u/mdbergmann)\
**Post date:** [February 6, 2022, 2:33pm UTC](https://erlangforums.com/t/problem-with-lfe-macro/1039/1 "2022-02-06T14:33:06Z")

</div>

Hello.

I’m having a problem with macro expansion.  
This is my macro:

```erlang
lfe> (defmacro foo (body)
       `(progn
          ,@body))

lfe> (foo (io:format "hello~n"))
** exception error: symbol io:format is unbound

```

Now when looking at the expansion it gets clear why it doesn’t work:

```erlang
lfe> (macroexpand '(foo (io:format "hello~n")) $ENV)
(progn io:format "hello~n")

```

But I don’t know what I did wrong. The macro seems OK to me.  
Can anyone spot the issue?

Manfred

---

<div class="post-metadata">

**Author:** ![starbelly](https://erlangforums.com/user_avatar/erlangforums.com/starbelly/32/209_2.png) [@starbelly](https://erlangforums.com/u/starbelly)\
**Post date:** [February 6, 2022, 8:02pm UTC](https://erlangforums.com/t/problem-with-lfe-macro/1039/2 "2022-02-06T20:02:06Z")

</div>

No LFE or lisp expert here, but I was interested : )

If you wrap your args twice in parens, it’ll work. This makes sense because :

This does not work.

```erlang
lfe> (progn io:format "hello~n")
** exception error: symbol io:format is unbound

```

But this works :

```erlang
(progn (io:format "hello~n"))
hello
ok

```

Thus,

```erlang
lfe> (defmacro foo (body) `(progn ,@body))
foo
lfe> (foo ((io:format "hello~n")))
hello
ok

```

Without the double parens and by the time @body is referred to in the macro it is the equivalent of

```erlang
lfe> io:format "hello~n"
** exception error: symbol io:format is unbound

```

It’s not clear to me how to wrap `@body` in the macro with parens so you could avoid doing it in the call to `foo` though.

You could also simply do :

```erlang
lfe> (defmacro foo (body) body))
foo
lfe> (foo (io:format "hello~n"))
hello
ok

```

But there may be problems with that at compile time?

I would ask @rvirding or @oubiwann for a technical explanation on this one 🙂

---

<div class="post-metadata">

**Author:** ![mdbergmann](https://erlangforums.com/user_avatar/erlangforums.com/mdbergmann/32/1243_2.png) [@mdbergmann](https://erlangforums.com/u/mdbergmann)\
**Post date:** [February 6, 2022, 8:28pm UTC](https://erlangforums.com/t/problem-with-lfe-macro/1039/3 "2022-02-06T20:28:22Z")

</div>

Thanks for responding.

I know from Common Lisp, that the &rest, or &body arguments in macros automatically add extra parens around the argument value, which are then again removed by the splice. Because the body could consist of multiple forms/sexprs.  
However, this doesn’t seem to be the case here. It should IMO not ne necessary to manually wrap it in more parens.

---

<div class="post-metadata">

**Author:** ![rvirding](https://erlangforums.com/user_avatar/erlangforums.com/rvirding/32/178_2.png) [@rvirding](https://erlangforums.com/u/rvirding)\
**Post date:** [February 7, 2022, 6:07pm UTC](https://erlangforums.com/t/problem-with-lfe-macro/1039/4 "2022-02-07T18:07:08Z")

</div>

There are a couple of things which cause this problem:

- `progn` takes a list of forms to evaluate and as your expansion expanded to

> (progn io:format “hello~n”)`

then it started evaluating each form one after the other. So first `io:format` which is an unbound symbol.

- It’s in the definition of the macro and and in `,@body`. When you define the macro as `(defmacro foo (body) ...)` you are saying that the macro when called should get **one and only on argument** and `body` will refer to that argument. So when you call `(foo (io:format "hello~n"))` then `body` will get the value `(io:format "hello~n")`. Now in a backquote using `,@` to expand a value will **splice** that list into the expansion which is why you got the flattened `progn`. This is how CL defines the backquote and how it expands.

So if you define the macro as

> (defmacro foo body `(progn ,@body))

then `body` will refer to the list of all arguments and the expansion will become as you wished it to be.

> lfe\> (defmacro foo body `(progn ,@body))  
> foo  
> lfe\> (foo (io:format “hello~n”))  
> hello  
> ok  
> lfe\> (macroexpand '(foo (io:format “hello~n”)) $ENV)  
> (progn (io:format “hello~n”))  
> lfe\> (foo (io:format “hello~n”) (io:format “there~n”))  
> hello  
> there  
> ok  
> lfe\> (macroexpand '(foo (io:format “hello~n”) (io:format “there~n”)) $ENV)  
> (progn (io:format “hello~n”) (io:format “there~n”))

If you look in the doc/lfe\_guide.txt in the Macros section it describes this and gives an example which is close to your macro.

---

<div class="post-metadata">

**Author:** ![mdbergmann](https://erlangforums.com/user_avatar/erlangforums.com/mdbergmann/32/1243_2.png) [@mdbergmann](https://erlangforums.com/u/mdbergmann)\
**Post date:** [February 7, 2022, 6:29pm UTC](https://erlangforums.com/t/problem-with-lfe-macro/1039/5 "2022-02-07T18:29:40Z")

</div>

OK, thanks for your response.  
I was actually looking through the documentation. Now that you say it I looked again and found this one:

```erlang
(defmacro my-list args
  "List of arguments."
  `(list ,@args))

```

Which indeed looks like what I need. But I guess the argument without parenthesis got me distracted and I thought: that cannot be what I need.  
So effectively a single argument without parenthesis represents a list of forms as body similar as the `&rest`, or `&body` arguments in CL.  
Excellent I will remember this.
