My point was different: mmm does not export ANYTHING. So using it will not lead to the problem of magically populating the namespace. The whole interface to the package is concentrated into mmm_API, which exports the developer-selected set of symbols. So using it would then be useful in the REPL and to document the interface to users, whereas using mmm: ... would be used in the package code.
If mmm exported things it would be very tempting to invoke using (or perhaps it would be done inadvertently). In this way is import mmm and using mmm are one and the same from the point of view of getting access to symbols.
Getting access to everything that is exported is now explicit, not implicit.
But that doesn’t do anything different than what using and import already does.
import mmm doesn’t export anything.
You don’t need a separate module to do that. If you want your imports to be documented in one spot, just do it:
So using it would be in useful in the REPL, and import mmm: ... would be used in package code.
It would be as indirect as using mmm_API vs using mmm, except it would be true for every Julia package so people would immediately know the difference by looking at your code, whereas mmm vs mmm_API would be something only you do.
No they aren’t. using is different than import. using allows things to be implicit, import makes it all be explicit. Using two separate modules with your own weird naming scheme to recreate what already exists in the language to do this only obfuscates the intention. There is not a single functional difference between your two module + know which one to using vs smartly choosing between using and import, other than the fact that the latter is standard across the whole language. I don’t get why you would not want to use the already existing standard to do exactly what you’re trying to do in less typing and with more documentation.
I don’t think you understand: mmm does not export anything. Hence it cannot be brought into scope implicitly for resolution of symbols. THAT is my point: import and using of mmm have the same effect. If the user wants implicit access, then it needs to be done by using a different module. The intent is then obvious.
I think here we are talking past each other: what you mean is what happens when someone accesses an already written module mmm. Then obviously there may be some exports already there. In that case you have the option of controlling access with either import or using.
What I mean is the point in time when the module mmm gets written. I’m saying that one can control the access to symbols from that module explicitly by not putting any exports in that module. For implicit access to the symbols that the module developer thinks are public is then through another module.
I don’t see the advantage of this compared to having a single module and import/using. Maintaining two lists of symbols violated DRY and puts an extra burden on the developer, merely to avoid using a mechanism that is already in the language. Perhaps I missed something.
Actually, the developer only needs to write one module, mmm, not to use any exports, and to describe which functions constitute the public interface of the module in the documentation at the top of the module.
The user (if they so desire) can write the module that explicitly makes some functions from mmm available for implicit access with using. For instance, if I use module mmm from the REPL all the time, I might wish to write the very brief module mmm_API that makes everything that I need available with one command.
So, as you can see I would tend to advocate for writers of library modules not to export.
If it is always the same list, a module would save some work, but at the same time it also adds overhead, and generally it loses the specificity that comes from a tailored import approach (I may use a specific subset for a project, and import allows me to be explicit about it).
I guess one could put the difference succinctly as who decides what is made available for implicit access:
(1) the developer, or (2) the user.
In the first case, the module mmm exports certain symbols. In the second case, the user is free to write a module that provides that implicit access, but using the module mmm itself does not lead to the problem of magically appearing symbols.
I am not sure I understand; with an explicit import list it is also the user who decides.
Maintaining a separate package-specific API module for some other package looks cumbersome, but perhaps this is because I have not seen it in practice. Can you link an example of a package that employs this technique?
You are absolutely correct, that is of course possible. My point was that if the user wished to do using to get the entire API available at the REPL, employing a separate module to do that is in my opinion preferable to the developer exporting the stuff once and for all.
module mmm # DEVELOPER WRITTEN: note NO explicit exports
"""
The "exported" function from this module is `publicfun`.
"""
function publicfun()
println("in publicfun()")
end
function _privatefun()
println("in _privatefun()")
end
end
module mmm_API # USER WRITTEN
# As one of the users who use `mmm` a lot from the REPL, I want to do `using mmm_API`
# to get implicit access to both the public function
# and the private function from the module `mmm`.
using mmm: publicfun, _privatefun
export publicfun, _privatefun
end
Just in case someone is interested: I figured out how to deal with exports for my package. It addresses the problem of control of conflicting exports by the USER of the package (instead of the DEVELOPER). Should you be interested, drop me a message. Or, have a look at GitHub - PetrKryslUCSD/FinEtools.jl: Finite Element tools in Julia …