Open-sourcing the Blue Style Guide for Julia

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.

2 Likes

You can do using Bar: Bar.

5 Likes

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)

4 Likes

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.

4 Likes

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”.

2 Likes

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.

Example,
https://github.com/Nosferican/Econometrics.jl/blob/27659194ced8c913ca06dec5b5b4a11e7d634df9/src/Econometrics.jl#L7-L36

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.

5 Likes

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.

1 Like

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).

2 Likes

You seem poised to cut a large swath :wink: I was talking more about files I can actually modify (i. e. that I own).

1 Like

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.

1 Like