You may want to import the functions from the module Foo
without bringing them into the scope of Bar
, so that you can make the function Bar.f
without having to take into account what methods of Foo.f
exist — e.g. if you don’t want to extend Foo.f
with new methods, but create your own function with the same name, which might have a completely different purpose.
You can do using Bar: Bar
.
Also, using Foo: f
allows one to be lazy and write f
unqualified. On the other hand, import Foo
requires that I qualify all symbols from Foo
, which is what I want when using Foo
in another module.
Don’t write that then… (using Foo: Foo
)
I find import Foo
more clear than using Foo: Foo
. But, if you can really do everything with using
, then the small loss in clarity is worth the simplicity obtained by ditching import
.
Apparently, this is not a minor issue. I just googled: julia difference between … (I was not looking for import and using), but it autocompleted to “using and import”.
The style I use concerning using
/import
is to always using
and the exact additions to the namespace. I only qualify when there is ambiguity (CSV.read
/ JSON3.read
). I only extend functionality to functions that are brought by import Pkg: method_I_will_extend
. I like the distinction and safe approach that follows.
The thing I don’t like about import Foo: bar
is that then in some other place in the code you see function bar(x::MyType) ... end
and it’s not very explicit that you’re extending some other package’s function rather than defining your own. I prefer to have function Foo.bar(x::MyType) ... end
whenever I’m adding a method to another package’s function.
The counterpoint would be that you can see every single function being extended in one place rather than go hunting across files to figure that out.
Not so. Do a “Find in the project” of for instance Base.count
(when extending count
). It pops up readily.
I think it would be harder to find if count
wasn’t prefixed with Base
.
You would have to do so for every function for every module (Base, Core, stdlibs, submdules, transitive deps, etc.). I like being explicit in one place rather than explicit each instance, but everywhere.
Just a suggestion: you could use GitHub releases to set up a versioning scheme for the style guide. That way users can point to a specific version, rather than having a moving target (as the language itself continues to develop as well).
You seem poised to cut a large swath I was talking more about files I can actually modify (i. e. that I own).
Good point - that’s a tradeoff. I think in practice I don’t often need to answer the question of which methods get extended, and generally if I want to know that I have followup questions about which of my types have new methods defined, so I think I end up going to the implementations anyways. But that seems like it’s wading pretty deep into personal workflow territory.