Most of the time, I’m a Python programmer, but sometimes I want to do something that requires compiled performance or a standalone executable or something, and I’m really interested in Rust as a complement to Python in my toolbox.
One of my favourite things about Python is that, if you’re following the style-guide, then every identifier in a source file is either defined in that file, or specifically imported at the top. Conversely, if you see a name imported at the top of the file and it’s not mentioned anywhere else, that means it’s an unused import and you can remove it.
In Rust, as far as I can tell this is almost true: it’s true for importing modules, but not for activating traits, which are lexically identical to module imports:
use a::Foo;
use b::Bar;
use c::Baz;
use d::Qux;
Quick, which of those is an unused import, and which is a trait activation that’s vitally important to the running of the code?
It’s probably too late to change this now, but I wish the trait activation syntax were visibly different from importing. For example, in the same way that you have mod foo { ... }
to define a module and mod foo;
to pin it in place, maybe you could have a trait declaration:
use a::Foo;
use b::Bar;
trait c::Baz;
use d::Qux;
Alternatively, you could split the two uses of use
with a modifying keyword:
use mod a::Foo;
use mod b::Bar;
use trait c::Baz;
use d::Qux; // this is a struct, not a module!
For backwards compatibility you could say that without mod
or trait
, use
guesses what kind of thing you’re importing, but let the style-guide encourage people not to make the computer guess.
(For completeness, it can also be confusing if you see code calling foo.bar()
and foo
does not implement a bar()
method. Obviously a trait is involved somewhere, but figuring out which one can be tedious. I can’t think of a way to make it not tedious without destroying the pleasant conciseness of traits, but at least if trait-imports were easy to spot, it would narrow the search space.)