Since modules are not tied to files, you can nest modules easily to achieve the split that you describe below, using `import` and `using` at the right places:
module Top import A import B module UseA using ..Top using A import B end end I rather suspect that this style might become a "best practice", such that at most one module is fully imported in any given module scope. I don't think this style is currently used much however . this is also quite similar to creating "conditional modules" ( https://github.com/JuliaLang/julia/pull/6884) > If I want to use f() from mymodule in the current module I can just do f(x) = mymodule.f(x). While valid (and I use this style definitions sometimes in my code), the semantics of this are very different from the current behavior. In the current behavior, defining a new method also makes that method available to all users of that original function. This is what makes `Base.convert`, `Base.call`, `Base.+`, `Base.start`, etc. very general. I use the alternative style definition when I have some reason that I want to significantly alter the method dispatch order. On Fri Jan 02 2015 at 8:50:28 PM samoconnor <samocon...@mac.com> wrote: > I've been trying to learn a bit about Julia's internals in the hopes of > understanding enough to be able to make some sensible suggestions on module > semantics. So far I've been buried in libuv land as a learning exercise... > https://github.com/JuliaLang/julia/pull/9450. > > It occurs to me is that it's nice to have a simple succinct semantic that > is immediately understandable, and to make sure that any convenience syntax > (or macros) that sit on top of that have no hidden magic. (I come from an > odd place called Tcl where there are only 12 rules > http://wiki.tcl.tk/10259) > Please excuse me if any of the following is obvious to those in the know, > or is silly in the context of Julia... these ideas are not fully thought > out yet... > > e.g. what if the only way to call a function in a different module was by > it's full name mymodule.f() and there is no using or import. > If I want to use f() from mymodule in the current module I can just do f(x) > = mymodule.f(x). > If I already have a function f(), then the semantics of how the > mymodule.f()'s methods get merged in are clearly defined by the existing > dispatch rules, no special module rules are needed. > > On top of that you could have functions or macros for "using" and > "import", but they would just be for convenience, no new rules. > > An example I've considered is a GUI toolkit or a plotting library where > you have possibly hundreds of functions and you don't want to be saying > FooBarGraphicsLibrary.display(my_window) all over the place, you'd rather > just say display(my_window). However, there is a problem with possible > unexpected dispatch results if you just splat all > of FooBarGraphicsLibrary's functions/methods into the current scope. Maybe > a good pattern is to have a macro that says @prefix "fbg_" > "FooBarGraphicsLibrary.* that does fbg_display(x...) > = FooBarGraphicsLibrary.display(x...) etc.. for all the functions in the > module. That way all the GUI toolkit functions names have an unambiguous > name prefix but they are not as long and unwieldy as using the full path > name. > > I think that importing large utility APIs is a very different use case to > e.g. importing a mathematical type API. If you import an API for imaginary > numbers, you want all the usual math functions to just work by the magic of > multiple dispatch. However, with something like a web-services API, or any > number of other system-programmng API's you probably want to avoid > ambiguous dispatch possibilities as much as possible and make it clear to > the reader of the code that "this is a call into wrapper library foo". > > There seems to be a tradeoff between on one hand having dynamically > loadable modules that are independently QAed and are guaranteed to have > certain behaviour; and on the other hand being able to import modules in a > way that gives rich interaction of types and dispatch (and the possibility > of full system optimisation etc...). Maybe these two use cases should have > different rules... >