rcm765
With the following code:
defmodule Foobar do
defmacro b(arg) do
arg
|> String.split("\n")
|> IO.inspect()
end
defmacro a() do
other(&b/1)
end
def other(thing), do: thing
end
during compilation of this module this error occurs:
** (FunctionClauseError) no function clause matching in String.split/3
The following arguments were given to String.split/3:
# 1
{:x1, [], :elixir_fn}
# 2
"\n"
# 3
[]
Attempted function clauses (showing 4 out of 4):
def split(string, %Regex{} = pattern, options) when is_binary(string) and is_list(options)
def split(string, "", options) when is_binary(string) and is_list(options)
def split(string, [], options) when is_binary(string) and is_list(options)
def split(string, pattern, options) when is_binary(string) and is_list(options)
(elixir 1.15.5) lib/string.ex:478: String.split/3
(stdlib 5.0.2) erl_eval.erl:750: :erl_eval.do_apply/7
(stdlib 5.0.2) erl_eval.erl:1026: :erl_eval.expr_list/7
(stdlib 5.0.2) erl_eval.erl:456: :erl_eval.expr/6
expanding macro: Foobar.b/1
#cell:opffgr7vdttksyult6zxtm6vlvo6paax:1: (file)
This implies that the code is being executed, but how and why?
Trending in Questions
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
Hello,
I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind.
However, when I launch mix phx.server, I get an error...
New
Hi everyone,
I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding.
I sta...
New
I’m working on a small exercise involving update_in/3, and I came up with this solution:
data = %{
name: "Periodic Table",
category:...
New
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication):
toke...
New
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New
** (ArgumentError) expected :max_attempts to be a positive integer, got: {:@, [line: 10, column: 19], [{:max_attempts, [line: 10, column:...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex










Showing Posts 1 to 7- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
sodapopcan
Isn’t it because you aren’t
quoteing it?kip
The first rule of macros is that the accept AST and they must return AST. The way this is typically accomplished is to wrap the code you want executed at runtime in a
quoteexpression. For example:Note that in order to apply the
arginside the quoted expression, it needs to beunquoted.rcm765
@kip, that’s not the issue here. The macro this was derived from is being passed in an AST. I’m just demonstrating how the code is be executed despite it not being called anywhere.
kip
Hmmm, other than disambiguating the reference to
&b/1I just copied and pasted intoiexand didn’t see the same output (Elixir 1.15.5, OTP 26)I mistakenly assumed the snippet posted wasn’t the full example, sorry about that.
rcm765
Yes I’ve confirmed the same on my end. Not sure if this should be considered a bug or not.
hauleth
It is called - there
other(&b/1). Macros aren’t (at least directly) available in runtime, so cannot be referenced. So what Elixir does is that it treat it the same way asfn a -> b(a) end, which mean it need to expandb(a)call. And there is where your code is evaluated.zachallaun
There are at least two things going wrong here:
@hauleth is absolutely right, the
&b/1is being rewritten tofn x1 -> b(x1) end. The macrobthen expands with the argumentx1, which is{:x1, [], :elixir_fn}as AST. This is why you see the{:x1, [], :elixir_fn}being passed toString.split/3in your example.Even if you rewrite the body of
ato handle a non-string argument, e.g. ignore the argument completely and just return:ok, returning the anonymous functionfn x1 -> b(x1) endfrombis invalid:To get things to compile,
aneeds to be rewritten to return valid AST:I suspect, however, that this might not address the actual code that this example was based off of. What I think you’re trying to do is to defer macro expansion until runtime. This isn’t possible except by evaluating a quoted expression, but that is a whole other can of worms. If this is the case, it’s worth reconsidering the approach.