On 09/12/2012 08:29 AM, Graydon Hoare wrote:
Apologies, this is my first email of the morning, with all the pedantry
and over-arguing for no good reason that implies. I've tried to keep it
brief but partly it's just a factor of time. Turn the mood-filter to
"not really as grumpy as this sounds", if possible :(
On 12/09/2012 7:36 AM, Patrick Walton wrote:
So instead of:
extern mod std;
use std::json::Json;
You'd write:
use std::json::Json;
The semantics of this would be that names of external crates form a sort
of "outer namespace" one level higher than the root of the crate being
compiled. Equivalently, it could be understood as "if regular resolution
of a module fails, try to load a crate". This would only work for "use"
statements; explicitly-namespace-qualified identifiers would not be
eligible for this magic.
This is what Python does, and it seems to work quite well for them.
Thoughts?
Not too keen, as-written. There might be something in this space we can
do, say 'use std = (<matchers>);' or something, but even that feels like
a toss-up in terms of clarity (see point 3 and footnote [1] below).
As written it suffers from three things that make me uncomfortable:
- Abandons the distinction between short-name lookup and metadata
matching. I know most of our testcases just said "use foo;" before
but anything for deployment or major reuse really ought to be using
metadata matching so it's somewhat robust against installation in
an environment with more than one thing called 'foo'. Also, we've
some (vague) plan to shift the package management scheme to using
matchers as URL sources for installing missing crates, and that
vanishes.
- Contravenes the explicit-is-better-than-implicit principle. Readers
don't know (and can't see) where the crate-dependencies are.
- Breaks the two-fold symmetry with other uses of 'extern' and other
uses of 'mod foo = ...'; I actually think this is quite a compact
factoring where the meanings fall out naturally from the code:
mod foo = "foo.rs" // compile-in other .rs files
extern { ... } // link-to non-rust, declared symbols[1]
extern mod foo = <matchers>; // link-to external rust code
extern mod foo; // short DWIM-form for same
I disagree with this symmetry argument and suspect the dual meanings of
'extern' will be confusing. An 'extern mod' is a rust crate. An 'extern
fn' is a non-Rust function. I also don't agree with reusing 'use' for
crate linking though, and I suppose I would just prefer a different keyword.
In general I'm a bit wary of optimizing this case too hard for ultimate
brevity. The 'use' directive that shows up a lot in programs is the one
managing the internal namespace. The linkage directives are few and far
between, and should usually all reside in one top-level file that is
barely ever opened or changed[2].
Personally, brevity is not my concern with 'extern mod'.
I really think the 'short programs' case shouldn't motivate design
choices. Truly short programs -- one-liners or the sort that wind up on
website front pages and might scare users off if too chatty -- just link
with libcore anyways, which is implicitly linked. Real crates can't get
by with tiny DWIM-y utterances because they need to be precise (and
offer information about URLs, versions, crate-wide compilation settings,
etc.)
I mean, I know we're "getting rid of crate files", in the sense of
eliminating the file-type distinction in favour of a couple special
syntactic forms, but in any nontrivial crate, top-level files with
similar amounts of chatter are very likely going to take their place.
Take a look at these:
https://github.com/mozilla/rust/blob/master/src/cargo/cargo.rc
https://github.com/mozilla/rust/blob/master/src/libstd/std.rc
I don't know that there's a way around it. If we don't write some of
this stuff down _somewhere_, it winds up in Makefiles, and then we have
two (well, like, 10) problems.
-Graydon
[1] As an aside about a 3rd possible use of 'extern', given that we need
_some_ word for this role in a couple contexts (the old uses of 'crust'
and 'native'), it's occurred to me that it might also recycle 'extern'
for the putative 'package-level export' we've sometimes talked about.
That is, 'pub' and 'priv' carry on meaning what they mean _within_ a
crate, but the question of whether a symbol is exposed for linkage from
_outside_ a crate could be predicated on the word 'extern', with the
default being 'anything pub', but overridden by explicit declarations.
I'm not crazy about overloading 'extern' further.
[2] Indeed, I'm still struggling with the issue of whether to re-enforce
a limit on where linkage declarations can even occur, so that the
compiler / package manager can _scan_ for them all without having to run
the entire front-end and elaborate any macros / evaluate all the
attributes. Initially 'use' directives were only allowed in crate files,
for just this reason, but that restriction vanished sometime around the
transition to declaring native-mods in separate files, killing off the
crate-evaluation phase and adding in conditional attributes. Still,
where we are presently is worrying; the compiler can't tell what it's
going to want to link until very late in the game.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev