christhekeele
I’m doing some questionable meta-programming, and could use your help!
I’m using Macro.prewalk to traverse some source code, with the goal of pruning entire expressions matching a pattern as I go. I would like replace the matching expression with a functionally “no-op” AST node, but so far everything I try displays as a value upon being passed to Macro.to_string, including:
nil{}[]{:__block__, [], []}(this becomes anilvalue)
Any ideas? Or elegant alternative approaches to pruning a node matching a pattern from a tree?
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
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
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
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 7- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
lud
If you want to remove matching clauses, you would generally remove them from a list of clauses:
But if for instance you have a
casewith a single clause, you cannot remove it, you must remove thecaseexpression entirely. And if the value of that expression is used, then you must remove that too, etc.A quick and dirty hack would be to replace your clause by a value that could never match, like a ref. You inject
never_match = make_ref()and then you replace the match clauses by^never_match.But it is a dirty hack. What are you trying to accomplish?
zachallaun
On my phone so can’t give a good example, but I’d recommend looking into Sourceror’s Zipper, which is a higher level structure that you can traverse over but has support for “remove the current node”.
linky
christhekeele
I’m trying to accomplish a dirty hack
. This is a DSL for personal usage only so I can make stronger guarantees—in this case, the expression I am trying to pluck (assignment to a specific variable I do not intend to reference again) I know I will only ever place inside a
:__block__, so it is safe to extract without modifying semantics unlike a->clause, and I validate the AST pre-and-post extraction. Would definitely never attempt this in shared code.Yep, reading thru various implementations it seems like the common approach here is to not to match on the expression node I am interested in directly in
prewalk, but prune it out from the list of expressions in the third position of an AST tuple before descending into it at all, with a special-case check that the top level node is not a match. Makes sense, though complicates the descent I’m doing as there are other cases in myprewalkI’m handling.These approaches work, thanks for the input—but I’m really more intrigued by the initial question, and want to leave this open to solicit more eyes:
Is there such a thing as a no-op “null” node in Elixir AST? I’ve spent quite a bit of time within the erlang compiler and am increasingly convinced there is not, but would be fascinated by a counter-example or core member refutation or confirmation of such a construct.
kip
I believe that would be the nearest to a no-op. Pretty sure I’ve used that for the same purpose but on my phone now so difficult to find.
christhekeele
Effectively, I’m wondering if there is a
t:Macro.output/0for whichString.trim(Macro.to_string(output)) == "".My intended usecase here is to extract something from code to prepare the code for textual display, so emitting a semantically neutral node is not quite what I want (and non-trivial, in a blocks-are-expressions-that-return-their-last-value language). I want it to be erased entirely, and a “null node” is an interesting concept.
mhanberg
It is also possible to use Macro.traverse/4 and on the pre order phase, replace the node with a sentinel like
:__remove_me__, and in the post order phase, find that node in the args (as someone said above) and delete it.The post order phase function being as simple as
christhekeele
Yep, IIRC that’s exactly what I ended up doing, making a two-tuple sentinel-node with a double-underscore atom, ex
{:__my_lib_sentinel__, inner_ast}.