trashyEx
Hello,
Probably related with macros (since I am learning them bit a bit), but let’s see if I can get some insight in what is going on.
I installed the decorator library (Elixir function decorators — decorator v1.4.0). Then, using a hello-world Phoenix project, I have a generic print decorator, but I would like to have a specific one for %Plug.Conn{}, and it does not work.
PageController:
@decorate print_conn()
def index_specific(%Plug.Conn{} = conn, _params) do
IO.inspect(conn)
render(conn, "index.html")
end
@decorate print()
def index_generic(conn, _params) do
IO.inspect(conn)
render(conn, "index.html")
end
The decorators from HwDecorator:
defmodule HwDecorator do
use Decorator.Define, [print: 0, print_conn: 0]
# at compile-time it does not know if is Plug.Conn
# def print(body, %{args: [%Plug.Conn{} = conn, _params]} = context) do
# so I assume we can work only with arity/2
# alternative, to mark with print_conn
def print(body, %{args: [conn, _params]} = context) do
quote do
IO.puts("Func Conn begin: #{Atom.to_string(unquote(context.name))}")
unquote(body)
IO.puts("Func Conn end: #{Atom.to_string(unquote(context.name))}")
end
end
def print(body, context) do
x = 3
quote do
# IO.inspect(unquote(context), label: "context") <---- WHY:2
IO.puts("Func begin: #{unquote(x)} #{Atom.to_string(unquote(context.name))}")
unquote(body)
IO.puts("Func end: #{Atom.to_string(unquote(context.name))}")
end
end
# This does not work:
# def print_conn(body, %{args: [%Plug.Conn{} = conn, _params]} = context) do. # WHY:1
def print_conn(body, %{args: [conn, _params]} = context) do
quote do
IO.puts("Func Conn type begin: #{Atom.to_string(unquote(context.name))}")
unquote(body)
IO.puts("Func Conn type end: #{Atom.to_string(unquote(context.name))}")
end
end
end
The function receives:
[{:=, [line: 8], [
{:%, [line: 8], [
{:__aliases__, [line: 8], [:Plug, :Conn]}, {:%{}, [line: 8], []}
]},
{:conn, [line: 8], nil}
]},
{:_params, [line: 8], nil}
]
So, I assume it is not matching since %Plug.Conn{} = conn is not the same as all those tuples from above.
I have 2 questions.
- WHY:1: What can be done to achieve using types in the decorator functions? Like, for instance, matching Plug.Conn with the first param? I annotate the type in
index_specificin case it helps, since I imagineindex_genericdoes not know it is Plug.Conn at compile time (where I suspect the macros/decorators are being executed).
== Compilation error in file lib/hw_phoenix_web/controllers/page_controller.ex ==
** (FunctionClauseError) no function clause matching in HwDecorator.print_conn/2
The following arguments were given to HwDecorator.print_conn/2:
# 1
{:__block__, [], [{{:., [line: 9], [{:__aliases__, [line: 9], [:IO]}, :inspect]}, [line: 9], [{:conn, [line: 9], nil}]}, {:render, [line: 10], [{:conn, [line: 10], nil}, "index.html"]}]}
# 2
%Decorator.Decorate.Context{args: [{:=, [line: 8], [{:%, [line: 8], [{:__aliases__, [line: 8], [:Plug, :Conn]}, {:%{}, [line: 8], []}]}, {:conn, [line: 8], nil}]}, {:_params, [line: 8], nil}], arity: 2, module: HwPhoenixWeb.PageController, name: :index}
lib/hw_phoenix/decorator.ex:28: HwDecorator.print_conn/2
(decorator 1.4.0) lib/decorator/decorate.ex:164: Decorator.Decorate.apply_decorator/3
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(decorator 1.4.0) lib/decorator/decorate.ex:128: Decorator.Decorate.decorate/4
(elixir 1.13.4) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
(decorator 1.4.0) expanding macro: Decorator.Decorate.before_compile/1
lib/hw_phoenix_web/controllers/page_controller.ex:1: HwPhoenixWeb.PageController (module)
- WHY:2: Why the
contextvariable cannot be used directly there? It is just an struct. I don’t understand whycontext.argsorcontext.namework, but notcontext.
== Compilation error in file lib/hw_phoenix_web/controllers/page_controller.ex ==
** (CompileError) lib/hw_phoenix_web/controllers/page_controller.ex: invalid quoted expression: %Decorator.Decorate.Context{args: [{:conn, [line: 14], nil}, {:_params, [line: 14], nil}], arity: 2, module: HwPhoenixWeb.PageController, name: :index_two}
Please make sure your quoted expressions are made of valid AST nodes. If you would like to introduce a value into the AST, such as a four-element tuple or a map, make sure to call Macro.escape/1 before
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
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
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 recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
So i have been using ash framework for a while and i love it. However currently the issue im having with ash framework is the error handl...
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
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
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
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
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
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
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 2- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
trashyEx
Any idea?
al2o3cr
%Plug.Conn{} = connis in fact exactly those tuples at compile-time:Check out the very final example from the
decoratordocs - inside the body of the decorator,context.argshas the a list of ASTs from the function’s head so the values can only be used inside of aquotewithunquote.