[rust-dev] Bikeshed proposal to simplify syntax
graydon at mozilla.com
Fri Jul 13 17:18:25 PDT 2012
On 12-07-12 11:41 PM, Sebastian Sylvan wrote:
> Hi Rust team! First of all, congratulations on the 0.3 release!
Thanks. The whole team continues to impress me too, the amount of work
this time around should not be understated (and not just churn; really
thoughtful and high-quality refactorings, a lot of hard problems).
> I have a bikeshed proposal to selectively simplify Rust's syntax in a
> way that has the side benefit of applying "negative syntactic
> pressure" on expensive constructs. It boils down to this: remove all
> special syntax for heap allocations and heap pointers.
Thus ~T becomes uniq<T>, ~expr becomes uniq(expr), etc?
> Allocating a block of
> uninitialized memory of type T might be heap_alloc<T>(), with the
> normal literals used to initialize it.
Note: we don't support allocating uninitialized memory.
> Now, this sounds a bit crazy, and I'm pretty sure it won't be adopted,
> but I'd appreciate it if you gave it a moment's serious consideration
> and thought about what the impact would really be. I don't think it
> would cost as much as you might initially think (modern C++ does
> essentially this with all the shared_ptr etc., and many of the actual
> allocation calls are hidden behind constructor functions anyway) and
> there are strong wins.
I agree that modern C++ does this, and it does relieve some syntactic
pressure (slack which C++11 seems to have gleefully soaked up). I don't
think that users having to write shared_ptr<foo> rather than @foo is
quite so clearly a "strong win" in our case, though.
> 1. Reduce the complexity of the syntax. In particular, reduce the
> amount of "special symbols". You've all heard jokes about Perl looking
> like line-noise, I'm sure.
I think this is a bit unfair; perl isn't even a context-free grammar. I
think we're in the same ballpark as Objective-C right now. And shrinking.
> Reducing the amount of special characters
> you need to know about before understanding code is a win.
True, but it's in tension with conciseness / expressivity. I initially
erred very much on the side of maintenance programmers in the design
(verbosity and clarity over expressivity) and am gradually being dragged
back towards the expressive side. This is one of numerous tensions in a
language; almost nothing is a pure win/lose, all is tradeoffs.
> Getting rid
> of some of the symbols and treating those types in a more regular way
> would also kill a lot of design problems like "what does a heap
> allocated fixed-sized vector literal look like"?
Unless you're planning on making our type parameters carry integer types
-- danger! -- this proposal doesn't help there.
> importantly, it would make it easier to see what a complicated type
> means because it would follow simple nesting rules that you already
> understand, because it's the same rules that apply to user-defined
> types. It would also make library-pointer types look like the "real
> thing" (e.g. arc<T>).
But they aren't. The compiler is doing a bunch of open-coding on those
pointer types, including reasoning about the initialization-state of the
pointee memory, enforcing kinds, generating visitors that walk through
them, and pattern-matching on the structure.
> 2. Apply selective negative pressure to constructs which should be
> avoided if possible.
Yeah. Again, this is in tension with "letting users write what they need
to". Rust initially prohibited even _cyclic_ memory and made all private
memory copy-on-write. Guess what was the first and most pressing request?
Second-guessing users and telling them they don't want to do what they
_do_ want to do is ... generally a losing game. @ and ~ are not
beautiful, and surely if someone can avoid reaching for them I wager the
noisiness and measurable performance cost is sufficient deterrence to
make the user think twice. I might be wrong, but ... the largest single
case of allocation is "", for example, and we _just_ started making it
obvious that those allocate.
(And we still have essentially _no_ code that emits static constants as
read-only memory, aside from fixed-size and slice-strings, and integer
constants. So ~"abc" actually hits the allocator every time, despite
being a constant.)
> preferred pointer should be the borrowed pointer. IMO, Rust makes it
> far too easy to allocate memory on various heaps - just add a little
> sigil and you're done. C makes you appreciate the implications of what
> you're about to do when you type "malloc".
Fair. It's true that we allocate too much presently. I believe a lot of
this comes from a combination of incomplete constant optimization (see
above), hiding the uniqueness of vectors and strings (no longer done as
of 0.3), and not having had the requisite technologies at our disposal
when writing the compiler, first-pass: our closures were weak,
borrowed-pointers nonexistent, interior-vectors nonexistent, arenas
nonexistent, etc. I would like to get some experience with using the new
technology in earnest, before looking at blunter instruments as you're
(Also: nobody's done the no-gc lint pass yet, but I fully intend to
provide it. Might just do so idly now, it's quick work)
> Anyway, as I said, I don't think this will gain much traction, but
> it's one of those small niggles that I would do differently if I was
> designing the language, so I thought I'd float it for consideration.
Sure. I appreciate the concern, I just think the weight of evidence
isn't _so_ clear that rust code "always" allocates too much, vs. the
current code doing so. I think it'll take some time to see. Also there
are a bunch of other factors at work, as I point out above (in terms of
the compiler knowing all about these pointers).
More information about the Rust-dev