Base is the standard library (the contents of base/). This is not imported
by default, so most modules will want to start with "import Base.*".
Main serves as the current open module when julia starts and you run a
script or begin typing at the prompt. whos() lists identifiers in Main.
Main has a special behavior: when a "module" expression is encountered,
the resulting module is stored in Root. In all other cases a module is
stored within the current module, creating submodules. Main imports Base.*.
The forms of "import" implemented so far are "import Foo", which imports
a single module, "import Foo.*" as discussed, and "import Foo.a" which
imports a single identifier from a module. Modules must explicitly
list exported identifiers using "export a, b, c, ...".
Currently "export" only affects which symbols can be imported into
other modules. All symbols can be accessed if they are qualified, e.g.
Base._jl_something_private. I was going to "fix" this, but I think it's
handy (especially for debugging) and we might just keep it this way.
Assignment of globals always takes place in the current module.
The syntax "M.x = y" does not work to assign a global in another module.
But, writing macros now requires awareness of two environments: the
macro definition environment (where the "macro foo()" body occurs), and
the macro use environment (where "@foo" occurs). The macro expander
performs an extra pass on the result of a macro to resolve symbols.
This is great! A few questions right off the bat...
Base is the standard library (the contents of base/). This is not imported
by default, so most modules will want to start with "import Base.*".
Are there situations where a package developer wouldn't want to import Base.*?
Main serves as the current open module when julia starts and you run a
script or begin typing at the prompt. whos() lists identifiers in Main.
Main has a special behavior: when a "module" expression is encountered,
the resulting module is stored in Root. In all other cases a module is
stored within the current module, creating submodules. Main imports Base.*.
To clarify, Main is the primary namespace that a script works in. When your script or a user in the REPL load()s a file with a module definition in it, that module becomes a sub-namespace of Root, which can then be imported with "import X" (would "import Root.X" work too?). Is that right?
julia> module Fooexport barbar = 1endjulia> FooFoo not definedjulia> barbar not defined
julia> import Foojulia> FooModule(Foo)julia> barbar not definedjulia> import Foo.*julia> bar1
The forms of "import" implemented so far are "import Foo", which imports
a single module, "import Foo.*" as discussed, and "import Foo.a" which
imports a single identifier from a module. Modules must explicitly
list exported identifiers using "export a, b, c, ...".
You mention submodules above. So if "module Foo" has a nested "module Bar", you'd import with "import Foo.Bar" or "import Foo.Bar.*" or "import Foo.Bar.Baz"?
julia> module Fooexport Barmodule Barexport bazbaz = 1endendjulia> Foo.BarFoo not definedjulia> import Foo.Barjulia> BarModule(Bar)julia> Bar.baz1
Currently "export" only affects which symbols can be imported into
other modules. All symbols can be accessed if they are qualified, e.g.
Base._jl_something_private. I was going to "fix" this, but I think it's
handy (especially for debugging) and we might just keep it this way.
I like this. It's Pythonic in a good way -- no shenanigans enforcing privacy.
It's interesting that you chose an explicit export statement, versus something like the Python rule that symbols starting with _ are not exported by "import Foo.*". I don't have a strong opinion, but curious if there's a rationale.
Does the export statement have to be in any particular place in the module definition? Is there a convention?
module Fuzzinclude("blurm.jl")include("fonz.jl")include("qux.jl")end
Assignment of globals always takes place in the current module.
The syntax "M.x = y" does not work to assign a global in another module.
If a module wanted a global variable associated with it, it'd create a setter function and then export that function?
But, writing macros now requires awareness of two environments: the
macro definition environment (where the "macro foo()" body occurs), and
the macro use environment (where "@foo" occurs). The macro expander
performs an extra pass on the result of a macro to resolve symbols.
I assume that older macros that used gensym will still work? It doesn't seem like this is a breaking change for those macros, but I might not be thinking it through...
Are there any modules, aside from the main four, in the codebase now? I don't see any in extras...
Btw, Jeff just dubbed this "the we are all consenting adults here" attitude.
--
Yup, common enough that I'm pretty sure I answered to someone's
question at Scipy'12 (talk or tutorial, can't remember) just by
quoting that, and pretty much everyone knows what is meant.
I have to say, big +1 to you guys for following that attitude.
Nothing that pisses me off more that bondage-and-discipline
languages... And congrats on the module system landing, this is a big
milestone for Julia!
I also wanted to publicly thank Jeff and Stefan for coming to
SciPy'12. It gave me an opportunity to quiz them over beers instead of
having to actually read the docs, but more importantly, it provided
multiple very useful discussions and what I hope will be the start of
fruitful cross-language collaboration and more idea transfer. Your
talk was excellent, I just hope the videos go up soon!
".. most of the time you will want to import Base.* "
There are not many circumstances where a Julia developer (and vanishingly few where a user) would choose not to import
e.g. error.jl expr.jl grisu.jl inference.jl promotion.jl ...
I do not see the balance in causing to be written "import Base.*" into so very, very many as yet unstarted source files.
Would you consider instead requiring that the developer write "nonimportable Base" (phrased as you like)?
I'd say to use explicit export declarations, but allow them to appear
anywhere in the module. So people who want them all at the top can do
so, and people who want each export declaration next to what it
exports can do that too.
--
Try ($esc(ex)). Extra parens are often the answer. I might change the parsing here at some point; not sure.
--