I would like to comment on several of your annoyances.
Generics with <>
Misuse of for indexed access. Having both () and doing roughly the same thing, especially since can be used to do arbitrary things, doesnât make sense. Pick one, use the other for generics.
So if I understood you correctly, you propose to use ()
for indexing in addition to method calls and []
for generics? I think it's not a good proposal, as []
is almost universally used for indexing and slicing in other languages, and having buffer(10)
will be quite confusing, as most of programmers will think about functions, not indexing.
:: vs. . is kind of unnecessary.
If you are talking about self
-less methods, then I kinda see the point, but I like the coherence which makes Foo.foo()
and Foo::foo(bar)
equivalent, i.e. .
is a nice hint that self
is implicitly used in a method call.
Closures could be made to look much closer to functions, but somehow arenât.
Any concrete suggestions?
âassociatedâ functions in trait impls. Iâd prefer separating them from normal functions and drop the self where possible.
You mean trait methods with default implementations? Do not forget, that those methods can be overwritten by implementations, which is often used for optimizations.
Arbitrary abbreviations all over the place. Itâs 2017, your computer wonât run out of memory just because your compilerâs symbol table stores Buffer instead of Buf.
The unneeded naming explicitness makes code harder to write and a little to read. I hope you don't want to use function
instead of fn
and begin .. end
instead of { .. }
.
Also, having both CamelCase and methods_with_underscores?
I personally don't see a problem with it. And I would've passionately hated CamelCase for method and function names.
iter(), iter_mut(), into_iter() ⌠decide prefix or postfix style and stick with it.
Choice of prefix or postfix mostly depends on how nice it will be to read. For example listed methods can be read as "iterate", "iterate mutably" and "convert into iterator", while iter_into()
would've been confusing. Is it "iterate into something" or what?
Type bounds are Sized by default, with some weird special syntax to opt out (?Sized).
Sized
trait bound is a rational default , otherwise we would've seen a lot of noisy Sized
bounds in our code. And with such default we need ?Sized
for opting-out. And I think it's a coherent choice with !Trait
bounds.
/// for normal documentation, //! for module level documentation. Documentation already uses Markdown, so maybe just let people drop a markdown file in the module dir? That would make documentation much more accessible when browsing through GitHub repositories.
And would've been a disaster for those who writes code. It's quite important to see documentation when you work with source code, and no, IDE is not an answer.
Also, documentation can cause compiler errors ⌠thatâs especially fun if you just commented a piece of code for testing/prototyping.
Can you elaborate? Also for commenting code you usually use //
or /* .. */
, which have nothing to do with documentation.
Type alias misuse: In e.g. io crate: type Result = Result<T, io::Error> ⌠just call it IoResult.
As a workaround I usually use io::Result
in my code, also you can write use std::io::Result as IoResult;
. But yeah, I agree that IoResult
would've been a better choice.
Macros are not very good. They are over-used due to the fact that Rust lacks varargs and abused due to the fact that they require special syntax at call-site (some_macro!()).
How special syntax results in "abusion"? And I don't see a connection between "over-used" and "macros are not very good". I agree that const generics, varargs and maybe some other features would've significantly reduced macros usage, but it does not tell us anything about quality of macro system. (though I certainly would like to see a good procedural macros system on stable)
println! and format! are very disappointing given that they use macros.
How do you propose to implement it instead? Don't forget about formatting string checks.