sezaru

sezaru

Proposal: Support for __PARENT_MODULE__ (or some other better name)

When writing my code, I always find __MODULE__ very useful to use as alias of that module “inner dependencies”, ex:

alias __MODULE__.{Impl, Helper, ...}

But one thing that I always find missing is that when I want to get some dependency for a module in the same “level” that my current module, I need to write the full module path, ex:

defmodule My.Big.Module.Path.Something do
  alias My.Big.Module.Path.SomethingElse

  ...
end

I feel that having something like __PARENT_MODULE__ would be useful in these cases. Also, the impact on the existing eco-system would be zero since it doesn’t break any existing code.

Here are more “concrete examples” of when this can come in handy:

When organizing behaviours

The way I organize them is something like this:

# The behaviour module
Some.Module.MyBehaviour

# The modules implementing it
Some.Module.MyBehaviour.Impl1
Some.Module.MyBehaviour.Impl2
Some.Module.MyBehaviour.Impl3

In these cases, I could write something like @behaviour __PARENT_MODULE__ and @impl __PARENT_MODULE__ instead of @behaviour Some.Module.MyBehaviour and @impl Some.Module.MyBehaviour

When organizing gen servers and scoped business logic

If my genservers are getting big or complex, I like to split them into smaller parts, normally what I do is have something like this:

# This module will have the genserver child_spec and public APIS
Some.Module.Path.MyGenServer

# This module will have all the genserver code implementation (handle_call, start_async, etc)
Some.Module.Path.MyGenServer.Server

# This module will have all the genserver business logic
Some.Module.Path.MyGenServer.Impl

# And this module will have the genserver state struct and how to create/update it
Some.Module.Path.MyGenServer.State

Now, for example, the Server module needs to call Impl functions, and the Impl module needs to call State functions. Making the usage of __PARENT_MODULE__ useful here.

I don’t know if that is normally an issue for other people, but the project I work is pretty big and have some pretty big module names, so having something like that would make writing some code way faster for me.

Most Liked

sodapopcan

sodapopcan

I don’t hate this and have found myself wanting it for cases like your first example. However, there is already confusion around there not actually being a module hierarchy and feel this could make it worse. It’s also something that won’t “just work” when you rename a module referenced by this.

Personally, I’m overall indifferent as I don’t find status quo to be too much of a pain.

jswanner

jswanner

To expand upon this with examples…

Module A.B.C is not contained within module A.B nor A, they are completely separate modules whose names start the same.

Even when writing code such as:

defmodule A do
  defmodule B do
    def b, do: "b"
  end

  def a, do: B.b()
end

Module A.B is still not truly contained within module A (A.B is not a child of A) but the above works as a convenience.

sodapopcan

sodapopcan

Your example of alias __MODULE__, as: User would definitely make grepping harder, though that is really only because of the :as. Personally I think :as should really only ever be used for getting around naming conflicts.

Otherwise for me I find the cognitive burden goes the other way. when I see __MODULE__ I immediately think “current module.” On the other hand:

defmodule Foo.Bar do
  # ... many line
  def something(%Foo.Bar{} = bar) do
    # ...
  end
end

Seeing %Foo.Bar{} here immediately makes me think “a remote module” and it often takes me many moments to figure it out, which sucks when you’re scanning.

sodapopcan

sodapopcan

Oh… ya I mean, different stokes, I guess. This would be crazy confusing to anyone coming in blind to this. I would first assume that Bar has been aliased in from another module but since it’s not explicitly present in the alias list, it then looks like a top level module. You have to “be in on it” to get it and even then, you can’t always be 100% alias __MODULE__ is present. This is terrible for scanning. But again, to each their own!

sodapopcan

sodapopcan

That module hierarchy in Elixir is an illusion and doesn’t exist. The . is lie! :ghost: Lots of people don’t understand this. Nested defmodules already make this confusing enough.

Maybe this one wouldn’t be as bad as I thought. I’d have think more on this one as it feels like it could possibly cause subtle bugs where a rename could result in it calling another function that happens to have the same name, but maybe not :thinking:


I should add that despite my indifference, I’d more than likely use this if it were available.

Where Next?

Popular in Proposals: Ideas Top

MeerKatDev
many times we do stuff like (e.g. test setups, json views in phoenix) aaa = ... bbb = ... ccc = ... %{aaa: aaa, bbb: bbb, ccc: ccc} and...
New
rhcarvalho
Hi all, I would like to gather some feedback before a more intentional proposal to add a new :depth option when specifying a Git depende...
New
rekkice
I’m building an editor integration to evaluate Elixir code in an IEx session. While Code.eval_string/3 allows tracking variable bindings,...
New
kip
Sumary of proposal DateTime.from_iso8601/3 adjusted to: set all numeric fields to the values as parsed (not shifted to UTC), preservi...
New
pdgonzalez872
Hi! There has been some discussion about hiring/jobs on here and I thought about running this by everyone. I wanted to try to help recr...
New
dli
Ecto currently supports some data-modifying WITH statements / CTEs for Postgres: Options: […] :operation - one of :all , :update_all ,...
New
winsalva
Hello all. First of all i’m running this using termux on an android phone. Running mix assets.setup shows this message 06:54:08.450 [de...
New
bartblast
This could resolve to {[a: 1, b: 2]}. Was it ever considered to allow such syntax? Notice this: {:abc, a: 1, b: 2} and this: my_fun(:abc,...
New
sezaru
When writing my code, I always find __MODULE__ very useful to use as alias of that module “inner dependencies”, ex: alias __MODULE__.{Im...
New
dkuku
This is a proposal to make the map key mismatch errors a bit better: Every time I have a typo It’s very challenging for me even when I u...
New

Other popular topics Top

SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement