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’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted”
Version...
New
Other Trending Topics
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
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
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
- #ecto-query
- #elixirconf-us
- #blog-post
- #ai
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










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.