The problem with that names are
private parts, because it’s not working as same as
private - here). The point here is to have different naming like
internal and optionally short it to
i instead of
defmodulep as well as
defprivate causes too many confusion. To be honest
defprivate is even worse, because it does not refers to
module in name.
defmodule Example do defprivate Sample do # … end defp sample do # … end end
Do you mean that
internal used this way will avoid the confusion?
defmodule Example do internal Sample do # … end defp sample do # … end end
Why not go for private then, it’s used practically in any language, even
Ruby refers to
private to declare a private something (a Module in this case) and uses the keyword
private to declare private methods
module A module B def self.a; puts("A"); end end private_constant :B def self.a B.a end end 2.3.1 :074 > A::B.a NameError: private constant A::B referenced 2.3.1 :075 > A.a A => nil
My initial idea was
defprivatemodule, but it’s too long and
def_private_module it’s not in style.
Maybe it’s a bias I have, but I prefer the emphasis on the
private part rather than on the
I said about
i and keep
module part which you didn’t.
So here is real example:
defmodule Example do defmodulei Sample do # … end defp sample do # … end end
Because private function (
defp) is working differently than private module in this proposal (
defmodulep). Look that private functions can’t be accessed in other modules at all, but there would be a way to access private modules even in other app (look my question about possible hack).
I’m sorry, I’m confused.
Do you mean
Of course private functions work differently than private modules, they serve a different purpose.
The proposal was about
private modules, but they are more like
I could have private modules with private functions…
In fact I probably will.
Yup as you talking about
defmodulep I’m talking about
i (just for example) ->
Now look that both
defmodulep refers to
private word as same as
defp, but as you see they work differently, so there can’t be
p word in proposed name. You know other languages, me too, but it does not mean that every newbie would know other languages as well.
private which means two different things could be confusing for beginners.
Not really a big difference…
internal are equivalent to my eyes.
I just see that
defmoduleinternal are longer then
defmodule and know it’s not a regular module.
In this regard, a
p at the end helps more than an
They are both private.
At a different granularity, but still private (AKA not accessible outside of their scope).
A private function is not accessible outside of the module that declares it, a private module is not accessible outside of <still debating>.
It really means the same thing.
It’s not a point to have big difference. The point is to have different naming even if those words are synonyms.
Again and again, helps for you, me and more experienced
Elixir developers. Beginner would be confused why
p does not work as same in both cases. Look that not everyone needs to read this proposition and not everybody even need to understand it.
No, they are not private as same as functions are. There are ways to access it outside unlike private functions. Depends on implementation there are few ways to access it.
defmodule Example do def private, do: 5 end defmodule Example2 do def private, do: "Sample" end
private, but 2 different implementations are 2 different implementations - not the same thing.
Imagine that I would write my own
phoenix library. It would be also server, but it would work differently. Naming it
phoenix is a big mistake as other developers seeing it could think that it’s fork or something like that. Looking at source they would find that there are 100% different even if both libraries do similar thing. Having same naming for different things is a big mistake as it’s confusing for others. While one team could assume that when we are saying
phoenix we mean something else other people would see it still as original
belonging to or for the use of one particular person or group of people only.
That’s exactly what
private functions and modules are.
But that’s not really relevant to the discussion, it’s just a minor implementation detail.
I guess we can agree to disagree on this.
defmodule Example do @doc "This belongs only to use of one particular person or group of people." def private, do: 5 end defmodule Example2 do @doc "This belongs only to use of one particular person or group of people." def private, do: "Sample" end defmodule PrivateTest do use ExUnit.Case do test "example" do assert is_integer(Example.private()) # 2nd assertion would fail assert is_integer(Example2.private()) end end # now look: defmodule Problem do def confuse(module), do: apply(module, :private, ) end Problem.confuse(Example) # Integer Problem.confuse(Example2) # String
Person A sign agreement for some job offer. Person B does not know if person A receives payment for hours, specific issue or maybe for whole specific project. That’s why person A should say is saying about agreement name instead of saying saying just about agreement. In any case he/she is working, but this does not mean all cases are exactly same. We could guess, we could assume, but nothing good would happen if we would do so.
That’s why people are using names. If you name something properly other people would understand you without taking care of “source”. Well we could name every pet just pet, because basically all pets are pets. Now you can’t filter images only for cats, because there are no cats - there are only pets. We could generalize everything and saying “thing” on everything, but that would be just confusing.
Just take a look at:
Now say again that private in both cases means exactly same.
This topic does not talk about making some modules private. We are talking about guarding some modules to … (show warning, don’t allow access it unless). This is definitely not how private functions are working.
You think that private is private and there is no way to access private modules. In my linked example I show how it’s possible in specific implementation case. That’s why I mean it’s confusing. They are named similarly, but works differently.
private, but here we have 2 different contexts which makes
private word more than one meaning and that could be confusing.
I really don’t want to monopolize the discussion.
Most of all, I’m not supporting any solution in particular, once we established private modules are going to be a thing, I’ll gladly accept any syntax for it, Jose and the Elixir team have already proven capable of handling those kind of changes with care.
definternalmodule they’re all fine to me.
But one thing is for certain: private modules are private modules.
They are something hidden from something else, based on some rule.
That’s not gonna change because rules are different for different elements.
Attributes are private too: they are only visible from inside the module and at compile time.
They just don’t have
private in the name.
Private functions are private as well (hence the name).
Think of them as something like
defp private_func, visible_to: [MyApp.A] do ... end
visible_to can be omitted and defaults to
Private modules are private in the same way, but from an higher level, since we are dealing with cross module visibility and given that modules have only been public until now.
The fact that privateness is not enforced doesn’t make them any less private.
A simple analogy is private offices: nobody is locking himself up inside them, anybody could open the door and see what you’re doing, but they’re private nonetheless, and people usually knock, even though they are not forced to.
No, I don’t.
I think it’s just a matter of smoothing the transition to a full private module implementation.
Besides, if we are going down that road and implementing them, I would prefer the real deal.
I would also have preferred
private to be an attribute of the module, even though I’m not a big fan of decorators, this one made sense to me and I think it’s more flexible.
I also think using
internal would cause major headaches when they are going to become
private for real (I bet it’s not gonna be that far in the future).
What’s going to happen to
will it be deprecated? or will it be repurposed?
In the end
private is just more future proof.
And the semantic is preserved.
The risk of confusion is exaggerated in my opinion: novices will read
private and think of something they should not rely on, just like
private functions, and that’ll be a good guess, even if they could work around the limitation, while experienced programmers are suppose to know what they are doing.
Yeah and that was a bit confusing for me at start. I though how could I fetch them from other module. Btw. you probably did not noticed, but there is option to do it.
yup, that’s 100% right
Now try to do that as a newbie and post a question on forum asking why it’s not working … It’s exactly why there should not follow same naming.
Or maybe other example. Write a library with
defp macros. Think now some library is using it and somebody want to contribute to it. Unfortunately your implementation does not support guards, so commits which looks good fails which confuses everyone. In hundreds of lines file you need to find
use which confuses everyone. Good if you are adding all declarations at top of file and you don’t have much of them …
Sorry, but I did not get what you mean by this. Is naked, shaved and young man still Santa Claus? It’s like lake without water is still lake. Of course it’s normal for
but definitely not for
Erlang private functions are definitely not like
Python private methods. Same difference is in
defmodulep. They have even different use case. First makes specific function private for specific module and second makes module magically hidden (for example scoped using some prefix). Hidden does not means private. Look that if there could be public database which is hidden and accessible only on specific IP address which is not assigned to any domain. It’s hard to find it, but it does not mean you can’t reach it. If you can reach it then it’s not private (again following what
Erlang offers as “private”).
defmodule Example do defmacro defmodulep(name, opts, do: block) do quote do defmodule Module.concat(Private, unquote(name)) do @visible_to unquote(opts[:visible_to]) unquote(block) end end end # requirep definition goes here end
Such code would simply add
Private. prefix before module, so you can’t access this module directly, but this just not mean that you can’t access it using
Private. prefix. Private modules therefore are not protected (like private functions). They are basically still Public, but hidden under prefix/scope.
Look if I would say that last day I had guest then what would you think? You would probably think about human in my flat/house, but I actually I could mean bot on website. Both human and bot can be guests, they could have actually same privileges and they even could want same thing, but this does not mean that they are exactly same. Basically bot and human are 100% different - they could use same tools, one could imitate other, but if we would say about them with same words then other people could misunderstand what we are talking about.
We could even group all pets under one “pet” word, because all are pets. Now you need to guess which pet I’m talking about, because they don’t have their own names like cat or dog. If you firstly thing about dog and you would hear from me that I let it go on his way (like cat does) then you would be confused why I did it. You would call somebody to catch it and they therefore would assume that you are talking about dog. Well … you basically talking about dog, but you actually you are talking about cat even if you did not noticed it. That’s confusion and mess.
From my experience more you assume is more problems in future. Having same naming (
private) for 2 different similar, but different things (hiding and protecting) would not give anything good. Every developer was newbie, so he/she should remember how much things he/she wrongly assumed. While
= operator is confusing it’s important for
Elixir itself. If we can we should not confuse newbie and don’t let assume too many things.
Coming from this point people (much more experienced from me) defined rules which makes everyone’s code easier to understand like proper indention, max line length, max function length and also proper naming. I believe most of things could be generalized to
z variables, but this does not mean that it should be done in such way.
And that makes them not private. There is even no way to protect use “private” modules in other apps. Still I could wrote
defmodule Ecto.MyHack do … end and I would be able to access all internal modules which are scoped for
Ecto.* modules only.
Again all what I mean is assuming what typical newbie do. Let’s say you have really important core function which you don’t want to be accessed. When you hear about “private” modules then you most probably assuming that they are working as same as private functions. If we would use synonym then newbie think:
Hey … why it's named differently? Does it not work like this one …?. This makes newbie curious about it and answer for his question would be available in documentation. If we would have same naming and newbie would assume that it’s working as same then he would not even look at documentation and would not notice that’s not working in same way. Wrong assumption could make code vulnerable and it could be pretty easy used with simple hacks I mentioned few times.
Imagine that someone would write library and instead of using private functions all write calls would be in private modules. This would allow to access them and write data for example without protection (like function guards) which is … not needed for “private” modules, because they are like private function, right? If I can imagine something like this in “5 min” then what could do expert taking his time with coffee cup?
ERROR: WRONG ASSUMPTION FOUND !!!
- Declaring the module visibility per package or application. The Elixir language and the compiler do not have the concept of “applications”. Applications and packages are purely a build tool construct. In a way this is great, because the language is small and we build features on top, but it also means we cannot implement a construct such as visibility per package as part of the language.
Also you really did not get why this proposal was created. It’s not about protecting specific module - it’s more about don’t give so easy access without any warning/error (depends on scenario). Access is still possible no matter if by hacks or not. It’s not going to be protected in future. This proposal does not mean that core team want to introduce private modules which in future would not allow to be accessed. This is all about don’t ignore reaching internal API.
Even if core team would change mind then they can’t change behavior of already implemented functionality until next major release i.e.
2.0.0. I don’t believe that
2.0.0 would be planned soon as there are not enough changes for such major version. Look that
2.0.0 means breaking backward compatibility, so core team would probably not dot it as often as you imagine, because there would be lots of problems with already created packages. Think that all authors of all packages would need to check if there are not any breaking changes in their code. This is lots of work and it would be definitely announced much before it’s release.
ok, I’m totally messed now …
Did you read proposal and why it was proposed? It was exactly because people tried to access things which they should not and it was not talked in contents of not used libraries, but lots of question/issues about “… not working after upgrade”. If there would be a way to access private functions I believe that lots of people would do so and I’m not exception here. I really often want to change one line in function which relies on few private functions, but copying them means maintaining all of this just for one line change and all fixes to this code would need to be tracked by me and patched in my version as well.
I’m curious what you mean by “experienced” developers, because if I remember correctly those awesome people which wrote
absinthe had problems with upgrading
Elixir too. Here are only few examples which are already mentioned:
and the complete list is really long.
Look I don’t believe that
José Valim would create such proposal for few newbies … There was lots of problems which I have noticed too using popular 3rd-party libraries.
Maybe after all of that you would not understand - no problem. I would like only to write why it’s so important for me. As a newbie I saw
monkey patching in
Ruby used only once for one line function. I liked it way too much. I end up with monkey patching lots of functions, because I just saw other people do that. Of course it was not only one thing I did wrong and mostly it’s all because I assumed too much. It’s why taking care about whole code (not only naming) is so much important for me.
Hope that helped
I think the bikeshed should be painted green, for what its worth
I haven’t read through all the threads on this topic but has the community thought about going the route Rust took, where every function is private by default? To make something public you have to declare it public like:
pub def this_is_my_public_facing_api(), do: # do something great
This way we don’t have to worry about private modules or whatever.
Since erlang requires a declaration of which functions are exported, yeah, I think the idea was considered. I have mixed feeling on the result, but I don’t question its consideration. In any case this is a majorly backwards incompatible change that would require a very strong argument to support it.
I just found defmodulep… Seems to me like the playground for the idea, or its the official implementation?
Any idea when
defmodulep will be available?
I don’t think
defmodulep was ever on a track to be generally available/used, it was created more as a proof of concept. And now that the repository is archived it will no longer be developed (although of course if it Apache v2.0 so you can fork and maintain it if you want).
But I think that Boundary - enforcing boundaries in Elixir projects is a more promising alternative so I’d recommend you take a look at that instead or develop a new library.
I know is archived, sorry to have mislead you about my intentions in my question. I don’t want to use it directly, but instead my question intention was when could we expect it in Elixir itself.
Any idea when Option A will be available in Elixir core?
I am not planning in developing a new library at all, and I already know about Boundary, but I was really expecting to have private modules in Elixir. I would prefer this to be built-in in the language then enforced by a dependency.
As mentioned in the proposal discussion, we favored option A and Boundary provides a more complete implementation - so I would advise to use that. We have no plans to introduce
defmodulep in core. You can see the proposal discussion for my rationale.