DidactMacros
Regarding AST form with qualified call
I’ve been reading a great AST guide that I really recommend.
One of the examples given in the first part correctly states that…
quote do
Foo.{Bar, Baz}
end
#=>
{
{:., [], [{:__aliases__, [], [:Foo]}, :{}]},
[],
[{:__aliases__, [], [:Bar]}, {:__aliases__, [], [:Baz]}]
}
There is an explanation given in the guide as to why the form [alias, :{}] is used, but I don’t really understand why there would be ambiguity in using the form below…
quote do
Foo.{Bar, Baz}
end
#=>
{
:.,
[],
[
{:__alias__, [], [:Foo]},
{:{}, [], [{:__alias__, [], [:Bar]}, {:__alias__, [], [:Baz]}]}
]
}
I put the above hypothetical AST in a Macro.to_string call, and I got the following error.
** (CaseClauseError) no case clause matching: :Bar
(elixir 1.16.0) lib/code/formatter.ex:2319: Code.Formatter.force_args?/2
(elixir 1.16.0) lib/code/formatter.ex:1172: Code.Formatter.call_args_to_algebra_no_blocks/6
(elixir 1.16.0) lib/code/formatter.ex:1109: Code.Formatter.call_args_to_algebra/6
(elixir 1.16.0) lib/code/formatter.ex:1056: Code.Formatter.local_to_algebra/5
(elixir 1.16.0) lib/code/formatter.ex:1695: anonymous fn/5 in Code.Formatter.args_to_algebra_with_comments/7
(elixir 1.16.0) lib/code/formatter.ex:1998: Code.Formatter.each_quoted_to_algebra_without_comments/4
(elixir 1.16.0) lib/code/formatter.ex:1984: Code.Formatter.quoted_to_algebra_with_comments/6
iex:33: (file)
Is my AST not correct?
Marked As Solved
al2o3cr
It’s only normally written in the context of an alias statement, like alias Foo.{Bar, Baz}.
Interestingly, the parser won’t let you write a function named {} explicitly, but one can be created by using a macro to build the AST:
defmodule WeirdMacro do
defmacro do_fun(name) do
{:def, [context: Elixir, import: Kernel],
[
{name, [context: Elixir],
[{:x, [if_undefined: :apply], Elixir}, {:y, [if_undefined: :apply], Elixir}]},
[
do: {{:., [], [{:__aliases__, [alias: false], [:IO]}, :inspect]}, [],
[
{{:x, [if_undefined: :apply], Elixir},
{:y, [if_undefined: :apply], Elixir}}
]}
]
]}
end
end
defmodule Foo do
require WeirdMacro
WeirdMacro.do_fun(:{})
end
Foo.{:arg1, :arg2}
I’m unsure when such a function would be useful - maybe in a complex DSL? - but it’s neat to see that it’s possible.
Also Liked
al2o3cr
The AST is expecting :__aliases__; not sure where the singular form has appeared from.
Fixing that in your sample AST and calling Macro.to_string produces:
Foo . {Bar, Baz}
It may help to contemplate this syntax, which expands to identical AST as Foo.{Bar, Baz}:
Foo."{}"(Bar, Baz)
Foo."{}" corresponds to {:., [], [{:__aliases__, [], [:Foo]}, :{}]}.
This is the same shape that a normal function call like Foo.huh(Bar, Baz) would produce, except the function being called has the otherwise-impossible name {}.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex










