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
