Adding __APP__ or something similar

72 views
Skip to first unread message

Dave Thomas

unread,
Nov 30, 2016, 11:40:41 AM11/30/16
to elixir-lang-core

I just tried to change the application name in a trivial Phoenix project. The name of the project is embedded into the source code 48 times. I have one controller, one view, and a channel.

My suggestion: assume anything created using mix will be build using mix. For these builds, add the definition __APP__, set to the application name (in module-name form) from the mix.exs file.

Then generate all the underlying files using

defmodule __APP__.EndPoint do
 ...

This could apply to both mix new and mix phoenix.new, as well as anything else that comes along.

Dave

Allen Madsen

unread,
Nov 30, 2016, 12:11:28 PM11/30/16
to elixir-l...@googlegroups.com
What happens when you have your app and a dependency that both use __APP__?

Allen Madsen
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to elixir-lang-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/fe291b67-82f9-411e-ae3a-a1821867ebc6%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Louis Pop

unread,
Nov 30, 2016, 12:20:24 PM11/30/16
to elixir-l...@googlegroups.com

How would a module know what __APP__ is? What would the rules be?

Cheers,
Louis


Drew Olson

unread,
Nov 30, 2016, 12:53:18 PM11/30/16
to elixir-l...@googlegroups.com
I'd personally rather focus community effort on refactoring tools to solve this kind of problem than add another magic name to the language.

On Wed, Nov 30, 2016 at 11:20 AM, Louis Pop <louisp...@gmail.com> wrote:

How would a module know what __APP__ is? What would the rules be?

Cheers,
Louis

On Wed, 30 Nov 2016, 17:11 Allen Madsen, <allen.c...@gmail.com> wrote:
What happens when you have your app and a dependency that both use __APP__?

Allen Madsen


On Wed, Nov 30, 2016 at 11:40 AM, Dave Thomas <da...@pragdave.me> wrote:
> I just tried to change the application name in a trivial Phoenix project.
> The name of the project is embedded into the source code 48 times. I have
> one controller, one view, and a channel.
>
> My suggestion: assume anything created using mix will be build using mix.
> For these builds, add the definition __APP__, set to the application name
> (in module-name form) from the mix.exs file.
>
> Then generate all the underlying files using
>
> defmodule __APP__.EndPoint do
>  ...
>
> This could apply to both mix new and mix phoenix.new, as well as anything
> else that comes along.
>
> Dave
>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an

> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/fe291b67-82f9-411e-ae3a-a1821867ebc6%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAM-pwt5n5eGKfNbfQyCoTX_0Cq8Fu%3DyXSA98EAMOtey_tchS%2Bg%40mail.gmail.com.

Dave Thomas

unread,
Nov 30, 2016, 1:20:38 PM11/30/16
to elixir-lang-core, dr...@drewolson.org
__APP__ comes from the mix.exs used to compile that module.

In a dependency, that dependency's mix.exs file is used, so __APP__ changes appropriately.

I don't want to have to use a refactoring tool to do this. I don't want to be forced to load up some special IDE to do something so core.

Dave 

Stanislav Mekhonoshin

unread,
Nov 30, 2016, 4:08:12 PM11/30/16
to elixir-l...@googlegroups.com, dr...@drewolson.org
As I think, __APP__ variable looks a bit ugly.
I think renaming application required not ofter.
Maybe it makes sense to add some mix task that can rename app?

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.

Michał Muskała

unread,
Nov 30, 2016, 4:34:06 PM11/30/16
to elixir-l...@googlegroups.com
How often one needs to rename the application? I had to do this only once, and it was a simple find & replace.

While __APP__ would simplify it, I find it a bit ugly to have every module defined like this. And if there was an __APP__ variable, I would certainly expect it to be the OTP application name, not some mutated module name. As of now there's no place in mix.exs that defines the "base" module for an application, and it's nor reliable to inflect it automatically from the OTP application name, some examples:

mongodb uses Mongo, mongodb_ecto uses Mongo.Ecto, phoenix_html uses Phpenix.HTML, phoenix_pubsub uses Phoenix.PubSub, cors_plug uses CORSPlug, plug_cors uses PlugCors.

I don't see a way how we can inflect those automatically.

Michał.
> --
> You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/fe291b67-82f9-411e-ae3a-a1821867ebc6%40googlegroups.com.

Michael Terry

unread,
Nov 30, 2016, 5:47:05 PM11/30/16
to elixir-lang-core

All the time. Naming things in programming is hard and I never get it right at first. Knowing that it may be a relative pain to rename a project later causes me to procrastinate on starting new projects a bit sometimes as I ponder what the perfect name should be.

Find-and-replace may work for Elixir, so that's nice, but in my experience find-and-replace often doesn't work trivially across programming projects, and that lack of trust is a problem. Just because it turns out that it can be done that way doesn't mean it's the best user experience. Making the obvious things easy should be a goal. 

Whether it's open-mindedly iterating on this proposal or a mix task I don't personally care, but we should recognize it's a valid pain point. There should be an Elixir-blessed solution to the problem, IMO.

- mt

Amos King

unread,
Nov 30, 2016, 7:03:44 PM11/30/16
to elixir-l...@googlegroups.com
Here here. 

Amos King
Binary Noggin
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

Ben Wilson

unread,
Dec 1, 2016, 8:16:09 AM12/1/16
to elixir-lang-core
FWIW I have renamed a couple enormous projects and in all cases it took basically 2 find and replace runs and a folder move.

Onorio Catenacci

unread,
Dec 1, 2016, 8:44:31 AM12/1/16
to elixir-lang-core
While I get your point, there's also the common use case of logging messages; that is, I usually include the app name in case someone decides to log everything to the same log.  There's also message displayed to the end user.  I mean I usually put something in the message about exactly which app it is in case the end-user decides to capture a screen shot or something like that.  For whatever it's worth, having a standardized variable like __APP__ would help with those use cases and make it a little easier to maintain.

oc

José Valim

unread,
Dec 1, 2016, 10:07:34 AM12/1/16
to elixir-l...@googlegroups.com
While I get your point, there's also the common use case of logging messages; that is, I usually include the app name in case someone decides to log everything to the same log.  There's also message displayed to the end user.  I mean I usually put something in the message about exactly which app it is in case the end-user decides to capture a screen shot or something like that.  For whatever it's worth, having a standardized variable like __APP__ would help with those use cases and make it a little easier to maintain.

Logger automatically includes the application in the metadata. You don't need to do anything besides configuring Logger to include it as part of the logged metadata:

config :logger, :console, metadata: [:application]

Onorio Catenacci

unread,
Dec 1, 2016, 10:14:30 AM12/1/16
to elixir-lang-core
I realized that was probably the case about 30 seconds after I posted my message @José. :)  In fact I thought about simply deleting my message but left it up there in case I was wrong. 

Ah well.  At least I know I'm thinking along the right lines. 

oc

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/jX9Pm2dTa-c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K5EvZvRumjHQrDQ9cOHjuL8J6MgmxiXDgOj492QwA2aA%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

Dmitry Belyaev

unread,
Dec 1, 2016, 5:18:55 PM12/1/16
to elixir-l...@googlegroups.com, Dave Thomas, dr...@drewolson.org
How would you reference the modules in such an application? Would you require a new way to define a global alias so you don't have to replace the original application name in the places of usage?

Dave Thomas

unread,
Dec 1, 2016, 6:03:34 PM12/1/16
to elixir-lang-core, da...@pragdave.me, dr...@drewolson.org
I don't think it's an issue. Once published, an app's name becomes part of its API. It would be bad manners to change it :)

José Valim

unread,
Dec 2, 2016, 4:33:34 PM12/2/16
to elixir-l...@googlegroups.com
As Michał said, I don't think we want exactly __APP__. After all, the application name is an atom, like :my_app, and we likely want the inflected application module, which would be MyApp.

Furthermore, as Michał also said, the inflection does not automatically work for all applications, so I believe we should rather explicitly say the top name module instead of inflecting it from a slightly related variable.

## Understanding the problem

If we take a step back, I believe the feature we are looking for is actually compiler constants. We want the ability to specify, when you compile this application, you are going to have this app wide constant with the value of X. For example, one could specify in their mix.exs:

def project do
  [constants: [APP: MyApp]]
end

And then you would:

defmodule __APP__.Foo do
end

The benefit of generalizing this mechanism is that we no longer need to hardcode to Mix and we can also make it work with the regular Elixir command line. As a matter of fact, both C and Erlang have this feature. In Erlang it is in the format of macros:

erlc -Dapp=MyApp

And in your code you would be able to access the app name as "?app".

## Existing solutions

Before proposing new solutions, let's consider if we can use anything that already exists today to solve this issue.

For example, maybe we could use application environment variables? Although defining a module like below probably wouldn't make anybody happy:

defmodule Module.concat(Application.fetch_env!(:my_app, :app), Foo) do

From the above, we also get the requirement the new construct must be concise. And we very likely want it to expand and be checked at compile time.

Hrm... wait... aren't we talking about module attributes? It has a concise syntax and expands at compile time. But wait... those only work inside modules. Maybe those could be extended?

## Proposing a solution

Left as an exercise to the reader. :)

The point of this email was to illustrate how we could generalize the proposal and see if we could adopt an existing solution or extend it somehow. Many options pass through my mind. For example:

1. Use @APP for compiler attributes (in contrast to @foo as module attributes). Pros: it is concise, can be made compile time. Cons: slightly new syntax, conflicts with __MODULE__ (which could arguably be @MODULE)

2. Use @app for compiler attributes. Compiler attributes could be overridden inside modules by a module attribute. Pros: it is concise, can be made to warn at compile time. Cons: overloads existing syntax.

3. Introduce a new syntax, such as $app. Pros: it is concise, can be made compile time. Cons: introduce completely new syntax, conflicts with __MODULE__ (which could arguable be $MODULE)

I am not effectively proposing *any* of them but I thought it would be interesting to keep the discussion going. After all my job is much easier if you do it all for me. :)




José Valim
Skype: jv.ptec
Founder and Director of R&D

On Wed, Nov 30, 2016 at 10:34 PM, Michał Muskała <mic...@muskala.eu> wrote:
How often one needs to rename the application? I had to do this only once, and it was a simple find & replace.

While __APP__ would simplify it, I find it a bit ugly to have every module defined like this. And if there was an __APP__ variable, I would certainly expect it to be the OTP application name, not some mutated module name. As of now there's no place in mix.exs that defines the "base" module for an application, and it's nor reliable to inflect it automatically from the OTP application name, some examples:

mongodb uses Mongo, mongodb_ecto uses Mongo.Ecto, phoenix_html uses Phpenix.HTML, phoenix_pubsub uses Phoenix.PubSub, cors_plug uses CORSPlug, plug_cors uses PlugCors.

I don't see a way how we can inflect those automatically.

Michał.

> On 30 Nov 2016, at 17:40, Dave Thomas <da...@pragdave.me> wrote:
>
> I just tried to change the application name in a trivial Phoenix project. The name of the project is embedded into the source code 48 times. I have one controller, one view, and a channel.
>
> My suggestion: assume anything created using mix will be build using mix. For these builds, add the definition __APP__, set to the application name (in module-name form) from the mix.exs file.
>
> Then generate all the underlying files using
>
> defmodule __APP__.EndPoint do
>
>  ...
>
> This could apply to both mix new and mix phoenix.new, as well as anything else that comes along.
>
> Dave
>
>
> --
> You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/64EDFB02-CE5A-42F5-B690-716E419E689A%40muskala.eu.

Adam Kittelson

unread,
Dec 2, 2016, 4:44:12 PM12/2/16
to elixir-l...@googlegroups.com
I realize they aren't proposals, but I do like #1, perhaps with an eye toward having @MODULE in conjunction with __MODULE__ for a time before eventually deprecating the latter.

Alternatively we could have @@compiler_attributes and @module_attributes because it would amuse me to have module attributes look like ruby instance variables and compiler attributes look like ruby class variables. ;)

Adam

Chris McCord

unread,
Dec 2, 2016, 5:05:54 PM12/2/16
to elixir-l...@googlegroups.com
I’m not yet sure how I feel about adding a feature to the language to solve this issue since I don’t think it’s hard to solve with find/replace and I’ve come to prefer the explicit, if not a little boilerplate'y namespacing. For the moment, I probably lean more towards -1. That said, I don’t particularly like solutions mentioned so far. Counterproposal:

1) we already have a configured `:application` module in mix. Let’s use Phoenix as an example:

mix.exs:

defmodule Phoenix.Mixfile do
  def application do
    [mod: {Phoenix, []}, …

So mix knows what module our “application” uses to start. What if mix can autorequire this module for us, and also auto alias this module to `App`? This would then allow us to write (or mix new to generate):

defmodule Phoenix do
  use Application

  defmacro defmodule(name, do: block)
    quote do
      defmodule unquote(Module.concat(Phoenix, name)), do: unquote(block)
    end
  end

  def start(_type, _args) do
  ...
end


Then any file in your project:

App.defmodule Router do
  ...
end


To me, this is the least magic’y way to solve the issue, doesn’t introduce any new syntax to the language, doesn’t introduce a way for folks to get carried away with globals, and doesn’t leave a bad feeling in my stomach like the others. Cons are that it introduces a single global alias, `App`.


To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CABqbXnuEd6gbBhv_Xop4%2BJARU%2BZt0w3%2BM-TaswjBvi2L_xVpng%40mail.gmail.com.

Chris McCord

unread,
Dec 2, 2016, 5:48:23 PM12/2/16
to elixir-l...@googlegroups.com
The defmodule macro is also something `use Application` could inject for us, i.e.:

defmodule Phoenix do
  use Application, alias: Phoenix

end

Amos King

unread,
Dec 2, 2016, 6:06:05 PM12/2/16
to elixir-l...@googlegroups.com
I think I like the App.defmodule more than the other solutions. It is more focused on the area of concern and doesn't need to be a new part of Elixir.

Amos King
Owner
Binary Noggin
=======================================================
I welcome VSRE emails. Learn more at http://vsre.info/
=======================================================

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages