What does 'use Mix.project' mean

Except that it is in the @moduledoc instead of documentation on the __using__ macro.

Which could have a typespec and a link to the source code…

1 Like

I think it fits best in the module documentation unless we add some special documentation rule for __using__ that makes it more understandable.

Functions and macros starting with __ are not meant to be called so documenting them explicitly would be confusing, the only other __ functions/macros we document are special forms because that’s the only way to document them.

You also have to already understand the relation between use and __using__. Typespecs for macros are pretty useless: @spec __using__(Macro.t()) :: Macro.t(). A link to the source would be useful but if that is required to use the macro then haven’t the documentation failed, and it’s not really hard to find __using__ if you follow the link to module source.

In essence, we can probably improve the documentation on use but then we need to improve the tooling in elixir/ex_doc for it since right now it would only make things more confusing for beginners. For now I think the @moduledoc is the best place for it and GenServer is a great example on how to do it.

I think that including explicit doc for __using__ might improve things for users who want to quickly discover the consequences of using a module. The @moduledoc section is most often designed as a tutorial, and so it contains a bunch of text. Even if the consequence of use are documented there, they are often hard to find.

The GenServer docs indeed explain the default implementation of each callback, but it’s not clear what are other consequences (if any) of use GenServer.

The __using__ doc looks like a good place where library authors can briefly explain the consequences of using. For example, GenServer docs could state that use GenServer injects @behaviour GenServer attribute and default implementations of callback functions. Mix.Project could state that some internal boilerplate is injected which allows the module to be used by mix. In Plug.Builder, using docs could also mention that some things are lexically imported.

Today, finding out such consequences of use requires reading the source code.

Another slight benefit of __using__ docs is that it would be a bit easier to get to the source code of the macro via the corresponding </> link in hexdocs.

5 Likes

__struct__/0 is a good example of a function that has special rules in ex_doc. Look at Task for example. defstruct/__struct__ [1] is documented but it shows up in docs as %Task{}.

We could make documenting __using__ show up as use MyModule in ex_doc and add h rules for it.

[1] https://github.com/elixir-lang/elixir/blob/v1.7.3/lib/elixir/lib/task.ex#L184

3 Likes

I think it’s disingenuous to say that __using__ has a typespec of __using__(Macro.t()) :: Macro.t().

The documentation for use GenServer takes a keyword list. I don’t think it’s fair to claim that I could pass any garbage Macro.t() I want to use GenServer and expect it to transform into a meaningful value.

As @sasajuric responded, there are ways to respond to this criticism without defensiveness, and to make an improvement on the language.

I’m not a core team member, nor am I much of a member of the community, but I think that it is on the core team to respond to criticism genuinely. It made sense to me that Joe might be interested in learning about this, but it felt like a real criticism of the way this language construct was being used when the creator of its predecessor is asking a question like this.

THIS: " The @moduledoc section is most often designed as a tutorial, and so it contains a bunch of text."

I agree. Having tutorials interspersed with the documentation often gets in the way. Sometimes you want a quick one-line explanation of a given feature. Or a succinct summary of purpose, usage and pitfalls.

Tutorials would work better if they were broken out elsewhere.

1 Like

It is not disingenuous, it’s actually how macros work. Consider this piece of code:

defmodule Foo do
  opts = []
  use GenServer, opts
end

In this case we are passing {:opts, [], nil} to __using__/1 which is not a keyword list.

That’s not how I was intending to come across. In this thread I believe I have explained what use Mix.Project does and explained how to find documentation and sources. I did post that we can improve things but I did not want to document __using__ because it has flaws. To quote myself:

[…]

I was not intending to be defensive, I was only trying to explain why I believe documenting __using__ has flaws. I also posted a suggestion for a solution which would improve __using__ docs:

Just to be clear, I don’t suggest removing the @moduledoc to other places. I think that introductory sections in the moduledoc are great, and in overall, my impression is that hexdocs works really good as a one-stop shop where one can find both introductory material, as well as detailed reference.

My point is that explaining use consequences in the introductory section (i.e. @moduledoc) will make such explanation harder to find. People learning e.g. GenServer probably don’t care immediately about the details of use, while people familiar with GenServer will have harder time discovering these details.