top | item 46046778

(no title)

movpasd | 3 months ago

You might this blog post interesting, which argues that it's Rust semantics and not syntax that results in the noisiness, i.e.: it's intrinsic complexity:

https://matklad.github.io/2023/01/26/rusts-ugly-syntax.html

I found it reasonably convincing. For what it's worth, I found Rust's syntax quite daunting at first (coming from Python as well), but it only took a few months of continuous use to get used to it. I think "Perl-esque" is an overstatement.

It has some upsides over Python as well, notably that the lack of significant whitespace means inserting a small change and letting the autoformatter deal with syntax changes is quite easy, whereas in Python I occasionally have to faff with indentation before Black/Ruff will let me autoformat.

I appreciate that for teaching, the trade-offs go in the other direction.

discuss

order

xscott|3 months ago

I'm not sure which of the dozen Rust-syntax supporters I should reply to, but consider something like these three (probably equivalent) syntaxes:

    let mut a = Vec::<u32>::new();
    let mut b = <Vec::<u32>>::new();
    let mut c = <Vec<u32>>::new();
    let mut d: Vec<u32> = Vec::new();
Which one will your coworker choose? What will your other corworkers choose?

This is day one stuff for declaring a dynamic array. What you really want is something like:

    let mut z = Vec<u32>::new();
However, the grammar is problematic here because of using less-than and greater-than as brackets in a type "context". You can explain that as either not learning from C++'s mistakes or trying to appeal to a C++ audience I guess.

Yes, I know there is a `vec!` macro. Will you require your coworkers to declare a similar macro when they start to implement their own generic types?

There are lots of other examples when you get to what traits are required to satisfy generics ("where clauses" vs "bounds"), or the lifetime signature stuff and so on...

You can argue that strong typing has some intrinsic complexity, but it's tougher to defend the multiple ways to do things, and that WAS one of Perl's mantras.

gpm|3 months ago

This is like complaining that in C you can write

    a->b
    (a->b)
    (*a).b
    ((*a).b)
Being able to use disambiguated syntaxes, and being able to add extra brackets, isn't an issue.

PS. The formatting tooling normalizes your second and third example to the same syntax. Personally I think it ought to normalize both of them to the first syntax as well, but it's not particularly surprising that it doesn't because they aren't things anyone ever writes.

iknowstuff|3 months ago

Most likely

    let e = Vec::new()
or

    let f = vec![]
rustc will figure out the type

Aurornis|3 months ago

> Which one will your coworker choose? What will your other corworkers choose?

I don’t think I’ve ever seen the second two syntaxes anywhere.

I really don’t think this is a problem.

bobbylarrybobby|3 months ago

I've only ever seen `a` and `d`. Personally I prefer `a`. The only time I've seen `c` is for trait methods like `<Self as Trait<Generic>>::func`. Noisy? I guess. Not sure how else this could really be written.

dontlaugh|3 months ago

This will be the case in any language with both generics and type inference. It's nothing to do specifically with Rust.

steveklabnik|3 months ago

I mean, the fact that you mention "probably equivalent" is part of the reality here: Nobody writes the majority of these forms in real code. They are equivalent, by the way.

In real code, the only form I've ever seen out of these in the wild is your d form.

jandrese|3 months ago

I think Perl-esque is apt, but that's because I've done quite a bit of Perl and think the syntax concerns are overblown. Once you get past the sigils on the variables Perl's syntax is generally pretty straightforward, albeit with a few warts in places like almost every language. The other area where people complained about Perl's opaqueness was the regular expressions, which most languages picked up anyway because people realized just how useful they are.

echelon|3 months ago

That's it exactly.

Once you're writing Rust at full speed, you'll find you won't be putting lifetimes and trait bounds on everything. Some of this becomes implicit, some of it you can just avoid with simpler patterns.

When you write Rust code without lifetimes and trait bounds and nested types, the language looks like Ruby lite.

When you write Rust code with traits or nested types, it looks like Java + Ruby.

When you sprinkle in the lifetimes, it takes on a bit of character of its own.

It honestly isn't hard to read once you use the language a lot. Imagine what Python looks like to a day zero newbie vs. a seasoned python developer.

You can constrain complexity (if you even need it) to certain modules, leaving other code relatively clean. Imagine the Python modules that use all the language features - you've seen them!

One of the best hacks of all: if you're writing HTTP services, you might be able to write nearly 100% of your code without lifetimes at all. Because almost everything happening in request flow is linear and not shared.

carlmr|3 months ago

>When you write Rust code without lifetimes and trait bounds and nested types, the language looks like Ruby lite.

And once you learn a few idioms this is mostly the default.

SoftTalker|3 months ago

This honestly reads like the cliche "you just don't get it yet" dismissals of many rust criticisms.

mrweasel|3 months ago

That article is really good, because it highlight that Rust doesn't have to look messy. Part of the problem, I think, is that there's a few to many people who think that messy version is better, because it "uses more of the language" and it makes them look smarter. Or maybe Rust just makes it to hard to see through the semantics and realize that just because feature is there doesn't mean that you need it.

There's also a massive difference between the type of C or Perl someone like me would write, versus someone trying to cope with a more hostile environment or who requires higher levels of performance. My code might be easier to read, but it technically has issue, they are mostly not relevant, while the reverse is true for a more skilled developer, in a different environment. Rust seems to attract really skilled people, who have really defensive code styles or who use more of the provided language features, and that makes to code harder to read, but that would also be the case in e.g. C++.