Is it necessary to warn about the @doc attribute for a private function

Is it really necessary for the compiler to spit out a warning about using @doc with private functions?

I don’t want to have to document my functions in two different ways. I want one clean way to present my comments to other developers throughout the codebase, at least at the function head.

I’ve seen others say, on this forum, that private functions aren’t meant to be documented because they are ephemeral. I believe this to be nonsense. Someone else not writing my code has no say in how long I keep my private functions around. I guarantee you even great developers like Jose Valim write private functions. You can probably find them in elixir’s code itself.

I don’t think we need an @docp or any modifiers to go with the @doc attribute. Just good ole @doc would be great for all functions.

Anyways, I know other people have asked the same question and get the same answer, but I think it’s worth drudging up again.


I have the same feeling about the warning, maybe not even using a new attribute like docp. If that warning is to warn you that you are documenting a function that will never used outside and maybe you declared it wrong by using defp instead of def then the undefined function check will catch it. Or if the documentation will not render on hexdocs it’s ok too it’s private the function will not appear there anyway. Just let us write our docs

Sure thing. What you are missing is the main point: if there is a need to document a private function, it means there is a need for other developers to use this private function, which means it should not be private.

Private functions are not meant to be re-used. Private functions might stay there forever, but they are just implementation details, they are none of anybody’s business.

If you find yourself explaining to mates what your private functions do, you are either teaching them Elixir in general, or doing it plain wrong.

Yeah sure, I get some of what you say, but I don’t think you’re thinking about every situation where you might want to document something you’re doing. Let’s say for instance you’re interfacing with someone else’s api which may be a little complicated, or maybe not. You may want to document why, or what the api is requiring from you in that function.

Or even better, this is a dynamic language, and not everyone uses dialyzer. You may want to document the format of the returned data.

Maybe i’m trying to conform to an RFC and I want to document where to find it.

There are plenty of reasons why I want to document something. All these “you’re doing it wrong if you have to document it” excuses is really just a blow off answer.

To directly answer your “it means there is a need for other developers to use this private function”, that’s not the only case. It’s possible that my logic is completely wrong, or something breaks later on down the road. I want to let the developer that comes after me know why I chose to do something the way I did, or what I thought my function was going to do/return.

I haven’t been programming for that long, but I swear I’ve never seen a community so against documenting their code or making others feel like dog crap for wanting to document theirs.


I never ever meant this. What I meant is being restrictive here, Elixir compiler plays the role of linter. There are 100 to 1 cases when documenting private functions is wrong. For the rest one still has any other type of comment, including but not limited to assigning the module attribute like

@future_readers """
This is implementing that, it’s done that way because of this. Thanks for understanding.

Allowing comments for privates because not everyone uses dialyzer is exactly what we are against of. It’s like allowing "0" == 0 because not everyone uses proper type conversions, IMSO.

This is kind of what I’m talking about “what we are against”. We who? The coding gods that say “Thou shalt program the way I want you to program?”

And, if the coding gods want us to always use Dialyzer, something that’s not even a part of the language, then the coding gods should make the language strongly typed.

I don’t buy this at all. If you’re writing code that is going to be pushed into production, and you’re not commenting it, you’re treating the people that are going to have to debug the code later just plain wrong.

It doesn’t matter that anyone here thinks that you shouldn’t write a private function, or whatever the case is. People are going to write code, and they’re probably going to write it in a way that you think they shouldn’t. It doesn’t matter. There still should be a standard way of documenting or commenting it. The way for that was chosen… @doc. That should be available everywhere.

1 Like

That is where you got it wrong. The way for that was chosen (by language creator.) This way is (like it, or hate it, it does not actually matter): you use @doc to comment public functions only, period.

There is nothing more overhyped for zero value than strong typing. It brings literally nothing save for headaches and enormously huge boilerplates.

This is the whole reason for this post. The fact that it can only be used for public functions. In my opinion, and obviously others since there are more posts on this forum talking about it, that it should be open to all functions, not just public.


That’s an opinion, and you already went against it when you suggested that commenting be replaced by using dialyzer, which is a typing addon to the language.

1 Like

I think the ‘problem’ is that there isn’t a way to just comment and document (in the ‘what this does’ sense, not the ‘create documentation’ sense) a function no matter what it is.

@doc is used to also create documenation automatically - hence people saying don’t use it for private functions, as you don’t want other people to consume those really.

What you want is something like a @nodoc or @docno that allows you to use the same format to comment code, but without it getting attached to auto generatred docs?

1 Like

That’s totally correct, but only for small projects which have always same team members. Bigger projects could share pretty simple API and do most of work in private functions. Also I would see some public functions as half-private i.e. available only for current library/project - something like dialyzer check for internal functions. Look how big changes could happen in some bigger companies. It could be really helpful if there would be a way to document internal part of projects which should be dedicated for future team members. Look that we still can’t move our minds to robots, so sooner or later everyone is going to be replaced by someone else. Current way of defining documentation could help people understand how to use specific library/project - not how it’s intended to work internally and not how it should be maintained in future.

For sure we can use comments like # TODO: description (of course really, really simple example) and create regular expressions in order to search for all places with such comment with shell commands like grep, but it’s not a solution which helps tooling Elixir. Libraries and projects like ex_doc can’t work directly on comments without extra tricks which are not needed for standard documentation. Such tricks does not allow to write simple tools enough quickly. Simply compare:

  1. depend on 3rd-party commands
  2. write extra code
  3. just fetch internal documentation by simple new switch in already existing API

I recommend to read:


And Jose and other people from core team ask community about thing they want to implement for sheer amusement. I don’t know Jose personally, but I will bet my arm, that he really cares about what people think about Elixir and read constructive criticism. More often than not he also acts upon it. Either by explaining why some things can’t be changed (easily), or by simple changing things. The way it is, You are wrong, period.

I’ve seen no study that was conducted in a good scientific manner, not biased, that proved your opinion. I have written in Python, Ruby, Elixir, and Rust, but also some JS, Java and C, C++. From my experience you have to write much more boilerplate code in dynamic languages. And by boilerplate I mean lots of tests that tests things that normally are guaranteed by compiler in statically typed languages. And in those dynamically to be honest I’ve seen lot of bugs in production environments that was due to wrong types of data being passed around, that could be avoided with static typing.

PS. Elixir is rather strongly typed language, same as Erlang, it’s just not statically typed. And let’s save ourselves discussion about how truly strong typed language should behave.


FYI: I never ever suggested anything like that, neither in this topic nor anywhere else.

I believe, reading and understanding what people reply is the significant part of any discussion.

How about dialyzer? If I remember correctly it have checks for that.

I tend to disagree; I am aware about @docp and family proposals. I am positive that documenting privates for the sake of having them documented does not solve the aforementioned issue.

No one single private function is documented in Elixir core and it still reads as a charm. The same works for Ecto. I believe (I did not check it carefully though) Phoenix is the member of that team as well.

Good design, encapsulation, SRP and common sense make the code readable without redundant docs. And as soon as the project is so complicated that it requires a documentation for developers (I could think of some math algorithms, or even ML,) the infrastructure to document it is worth to be built from the scratch with the needs of this particular project in mind.

I don’t think that a team wanting to keep their private functions documented - maybe with a link to an internal wiki page, or explanation as to why something is done how it is etc - is a bad thing.

It helps junior developers when learning, it helps when memory fades and you can’t remember why something was done a particular way etc

Adding a way to document private functions doesn’t affect anyone not wanting to use it in anyway, but helps out those that do want to use it greatly

Dialyzed is great, but it’s spec are not part of the actuall implementation. You can have perfectly valid code and dialyzed warnings because of wrong types (lot of libraries have wrong dialyzed types, or at least incomplete ones). Or you can have bugs in code, but no dialyzer warnings because of, again, wrong specs.

That is true, but also it implicitly makes the developers to think less about what is to be made private and why. Also, it obsoletes the documentation or implies the redundant changes when the implementation details are changed.

The same reason drives an unwillingness to make private functions testable.

Implementation details should not leak in any way, even if it sounded as a good intention at a glance.

1 Like

oh, looks like that I’m much bigger noob than I originally expected :077:

For example one time I have entered random file in ecto repository and totally did not get most of things written there (working on Elixir AST). After some time I started to understand more, but to do it I have going through docs like compiler - from start of public call to last private function. I’m able to find old discussion which describes why they follows such way etc., but I still need to spend some time on it rather than just read directly. I don’t believe that every beginner would understand any random private function especially from Elixir core which is partially written in Erlang.

btw. I think that you are a bit wrong. For example take a look at: ecto/lib/ecto/query/builder/select.ex and look that Ecto.Query.Builder.Select module is considered to be fully private (@moduledoc false), but there is still written documentation for Ecto.Query.Builder.Select.escape/3 function. It’s internal function, but it’s also still documented. It should never be shown in ex_doc, but for some reason it’s still documented.

1 Like