4 ms·
Meanwhile Rust is noncompelling due to its syntax. It made a bunch of weird design choices (like putting class methods in separate `impl` blocks) that have ruin
by LorenDB 3y ago
Meanwhile Rust is noncompelling due to its syntax. It made a bunch of weird design choices (like putting class methods in separate `impl` blocks) that have ruined my chances of trying to use it for any personal projects.
- Klonoar 3y agoThat’s a subjective matter of taste.
- LorenDB 3y agoYes, but I think you'll find that many people tend to resist change, including drastic syntactic changes (as compared to how languages like D iterate on previous languages like C++).
- lifthrasiir 3y agoRust specifically changed its syntaxes to resemble C++. For example the turbofish syntax `::<T>` is actually a highly bad choice by its own, but was deemed more familiar to C++ users who are used to `<T>` (which was too ambiguous so had to be tweaked though). Even `return` was spelled `ret` back then!
- nicoburns 3y agoRust syntax isn’t really that novel. It’s not exactly like C, but most of its syntax is pulled from some popular language: some from C, some from JS, some from Python, some from ruby, etc.
- aldanor 3y agoA lot more from ocaml than js/Python/ruby.
- littlestymaar 3y agoLots of concepts come from Ocaml, but syntax-wise, Rust is closer to JS than to anything else.
- School-Cotton 3y agoThat’s one of the most trivial imaginable reasons for choosing one language over another.
- johnbingus 3y agoI actually quite like that, because it makes it clear that the impl blocks aren't class methods, they're trait implementations. Maybe they could have chosen a better keyword, but having traits (aka typeclasses) instead of classes helps you mitigate the expression problem[1] and some other nasty things quite a bit. [1] https://en.m.wikipedia.org/wiki/Expression_problem https://en.m.wikipedia.org/wiki/Expression_problem
- xpressvideoz 3y agoThere are a plethora of languages that allow implementing methods outside of a class block, including Java, Kotlin, Haskell, C#. And many of them are mainstream. Your argument seems weak.
- dureuill 3y agoYou make it sound like Rust made these choices for the heck of it, whereas there are very good reasons why impl blocks are separate from the struct: 1. Make class methods open to extension. This allows adding methods from other contexts, including other privacy contexts. Sure you could have dedicated syntax like C#'s extension methods, but these were added after the fact. If starting your language from scratch, while have two distinct syntaxes, when one will do? 2. Allows to add methods that only exist for some combinations of generic parameters. For example you can have a generic `Foo<T>` class, and then define a method `from_bar` that only exists for `Foo<Bar>`. Again, impl blocks may not be the only solution to this, but it is a highly cohesive one. 3. Lastly this is more philosophical, but it decouples the data definition from the method definition. Not wanting to try Rust because its syntax is unfamiliar has to be the weakest reason, especially when the syntax has excellent reasons to be different.
- nextaccountic 3y agoimpl blocks are actually more powerful than class methods because if you have a generic struct or enum MyType<T>, you can have a method for all MyType<T> or for just MyType<Something>
- tines 3y agoPutting class methods in separate impl blocks is actually objectively better; it allows you to define new methods on types that you didn't write, like typeclasses in Haskell.
- tialaramex 3y agoNotice Rust actually forbids you from doing this to types you don't own. Rust's own standard library gets a pass. For example the [T] (a slice of T) generic type is a built-in, and the core library defines methods on that type, but in terms of sorting it only provides sort_unstable - an unstable sort, and the associated variants of that sort. Then Rust's alloc crate, which is optional, has a new impl block for [T] and it defines sort, a stable sort on this same type which is much faster than it might be otherwise because it uses a temporary buffer, hence it needs an allocator and can't live in core. You are not allowed to do this for other people's types. If I make a Goose in crate A, and then you try to write an impl block for A::Goose so that you can add a fly method to it, that won't work. Rust obviously could allow this, but it would invite chaos, so they don't. What you can do is invent a trait Flying and impl Flying for A::Goose
- lf-non 3y agoYeah I found it somewhat surprising too. Coming from kotlin I had expected this to be similar to extension methods but apparently not. I never fully understood the motivation behind this restriction.
- tialaramex 3y agoSuppose I use Jim's birds crate, Sarah's noises crate and Hannah's shape crate. If Hannah is allowed to write impl birds::Goose { fn fudge(&mut self) { self.counter += 1; } } and Sarah is allowed to write impl birds::Goose { fn fudge(&mut self) { self.counter -= 1; } } ... Now what happens when I call fudge on a Goose? Does it increment the counter? Or decrement the counter? If instead the program is rejected because of the ambiguity, whose fault is the ambiguity? Sarah's fault? Hannah's fault? Jim's fault?