Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Rust promote use statements with explicit imports?

Tags:

rust

I see a lot of Rust code where the use statements look like this:

use std::io::net::ip::{SocketAddr, Ipv4Addr};

The way I get it, this restricts the use statement to only import SocketAddr and Ipv4Addr.

Looking from the perspective of languages such as Java or C# this feels odd as with such languages an import statement always imports all public types.

I figured one can have the same in Rust using this statement.

use std::io::net::ip::*;

The only reason I could see for the explicit naming would be to avoid conflicts where two different imports would contain public APIs with the same names. However, this could be worked around with aliasing so I wonder if there's another advantage of the more strict "import only what is needed" approach?

like image 531
Christoph Avatar asked May 23 '14 23:05

Christoph


2 Answers

Rust is in this inspired by Python, which has a similar principle: importing is all explicit, and though glob imports (use x::* in Rust, from x import * in Python) are supported, they are not generally recommended.

This philosophy does have some practical impacts; calling a trait method, for example, can only be done if the trait is in scope, and so calling a trait method when there are name collisions in the imported traits is rather difficult (this will be improved in the future with Uniform Function Call Syntax, where you can call Trait::function(self) rather than just self.function()).

Mostly, though, it is something that is well expressed in the Zen of Python: "explicit is better than implicit". When vast swathes of things are in scope, it can be difficult to see what came from where, and intimate knowledge of the module structure, and/or tooling becomes quite important; if it is all explicit, tooling is largely unnecessary and working with files by hand in a simple text editor is entire feasible. Sure, tooling will still be able to assist, but it is not as necessary.

This is why Rust has adopted Python's explicit importing philosophy.

like image 74
Chris Morgan Avatar answered Nov 05 '22 05:11

Chris Morgan


  • Mailing list thread asking why glob imports are not preferred

in which Huon writes

Certain aspects of them dramatically complicate the name resolution algorithm (as I understand it), and, anyway, they have various downsides for the actual code, e.g. the equivalent in Python is frowned upon: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#importing

Maybe they aren't so bad in a compiled & statically typed language? I don't know; either way, I personally find code without glob imports easier to read, because I can work out which function is being called very easily, whereas glob imports require more effort.

  • Issue to remove glob imports

where nikomatsakis writes

I think glob imports have their place. For example, in the borrow checker, there is a shallow tree of submodules that all make use of data types defined in borrowck/mod.rs. It seems rather tedious and silly to require manual importing of all these names, vs just writing use rustc::middle::borrowck::*. I know that there are complications in the resolution algorithm, though, and I would be more amenable to an argument based on fundamental challenges there.

This then moved to RFC 305 which was rejected by steveklabnik without comment on whether they're good style:

Glob imports are now stable, and so I'm going to give this a close.

like image 45
Jesse Ruderman Avatar answered Nov 05 '22 07:11

Jesse Ruderman