lkuty
I have a module for which I want to create a function rule_ids/0 at compile time. The code collects the rule ids at compile time from the first argument of all clauses of the function condition/3 using the AST.
It does not work because the variable rule_ids_ defined at compile time is not accessible when defining the function with def rule_ids(), do: rule_ids_.
How could I proceed to get it working? Should I use a macro somewhere?
defmodule Rules do
# Collect the rule ids at compile time
{_ast, rule_ids_} = File.read!(__ENV__.file)
|> Code.string_to_quoted()
|> Macro.traverse([],
fn
{:def, _, [{:condition, _, [rule_id, {:v, _, nil}, {:site, _, nil}]} | _]} = x, acc -> {x, [rule_id | acc]}
other, acc -> {other, acc}
end,
fn other, acc -> {other, acc} end
)
# How could I use rule_ids_ here?
def rule_ids(), do: rule_ids_
def condition(rule_id, v, site)
def condition(1018, v, site) do
v[site][7018] < 50 && v[site][7019] < 50 && v[site][7020] < 50
end
def condition(1017, v, site) do
v[site][7027] > 42
end
# ...
end
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,
I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
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
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
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
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
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
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
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
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
D4no0
These is what module attributes are for: Module — Elixir v1.20.2
I’ve never checked it, but this should work:
LostKobrakai
There are better ways to do this over reading “yourself” and parsing the AST.
You can use
@on_definitionon a module (sayA) to have it call a macro or function elsewhere (Say onB) whenever a function or macro is defined on the module. With a macro being provided you can then pull information from those definitions and store them in an arbitrary module attribute ofA.You can register another callback
@before_compileinA, which calls the callback macro (likely also inB) right before the module starts compiling, but after all it’s body has been evaluated. That module can then read your arbitrary module attribute for all the gathered information and turn it into AST returned from the macro. That AST is then added to the module – you can imagine it being injected right before theendline ofdefmodule.lkuty
It worked with:
lkuty
I’ve put
@on_definition {Hooks, :rule_ids}in moduleRulesbut in the other module calledHooksI cannot see how I can accumulate the ids and make use of them in therule_ids/6function.LostKobrakai
You can use
Module.put_attribute, though I thinkHooks.rule_idsneeds to be a macro for that to work. The module attribute needs to be one on the module being compiled though, not on theHooksmodule.lkuty
I managed to make it work using both your advices. In fact I thought you had given two different ways of doing things but it looks like we have to combine them.
LostKobrakai
Yeah, that’s what I was hinting at. You can remove the hardcoded
Rulesin theHooksmodule by replacing it withenv.module. Often all the boilerplate you have inRulesis also contained in a__using__macro ofHooks, so ause Hooksdoes everything you need withinRules.mudasobwa
While everything suggested above is absolutely correct, I’m to answer your original question.
One does not technically need module attributes, nor hooks here. The issue is scopes and we have unquote fragments for that.
rule_ids_is defines in the outer scope forrule_ids/0call, therefore one needs to unquote it there. THe code below would work (I also fixed the issue withcondition/3head mistakenly falling under a match during the parse stage.)