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 suggesting here.

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

-Graydon
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to