Let me start by saying that while I have done some basic coding in Elixir and messed with Ecto and Phoenix I am coming from a mostly Ruby/class-based OOP background, and I can tell I have a lot brain-training to do. The main issue is dealing with immutable structures. It’s been smooth sailing thus far actually but… in a project I’m messing around with I’ve hit an issue.
Let’s say I have a struct/module named Thing
. A Thing
can be related to other things via some kind of value—let’s say I just have a key named relationships
. The problem I see is when you have a struct of thing1
and thing2
that relate back and forth. If this was OOP and I was building a class or even a simpler structure like a hash, thing1
would get created first then you’d create thing2
and probably have it point back to thing1
. From there you’d mutate thing1
's relationships to point to thing2
. However, since I cannot mutate thing1
, changing the relationships results in a new struct which points to thing2
which points to the old thing1
.
At runtime it seems like you can accomplish this with a GenServer. All the Thing
things understand that they need to talk to a GenServer and related a name. In this case, thing1
would have a reference to a name “thing2” that, at some point in the future, would resolve to the actual thing2
once defined.
What I really want is a global map available at runtime but generated dynamically at compile time. In terms of OOP, these structs are just “instances” of Thing
. What would be better would be to have a module named ThingsRegistry
with a function called get
that took a string or atom and returned a named struct but, unlike a GenServer is not a process but rather the map that get
is reading from has been set at compile time and perhaps register
to replace the name map.
Can a macro take an existing function, get the return data, and then overwrite it?
I understand that I might be thinking about this all wrong and if that’s the issue, please feel free to let me know.