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*
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D

On Wed, Nov 30, 2016 at 10:34 PM, Michał Muskała <[email protected]> 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 <[email protected]> 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 [email protected].
> > 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 [email protected].
> To view this discussion on the web visit https://groups.google.com/d/
> msgid/elixir-lang-core/64EDFB02-CE5A-42F5-B690-716E419E689A%40muskala.eu.
> 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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BwQoC6mggL1QiU1auT27krVEcWcsNiQqcJTj7J9kU3bw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to