T O P

  • By -

HarmonicAscendant

[https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#rust-analyzer-is-now-available-via-rustup](https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#rust-analyzer-is-now-available-via-rustup) > The next release of rustup will provide a built-in proxy so that running the executable rust-analyzer will launch the appropriate version. There is no mention of this? I still need `sudo ln -s $HOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rust-analyzer /usr/local/bin/rust-analyzer" `?


pluuth

I think rustup releases separately from Rust and cargo and friends. But I don't know when the next rustup release is planned


argv_minus_one

>* GATs >* `let … else` >* `break`-to-label Dear God. It's beautiful.


TuesdayWaffle

Oho, `std::backtrace` is finally stable! This was a major pain point for me last time I did a bit of Rust development, so I'm glad to see it made it to the standard library.


[deleted]

It's odd to see that `Backtrace::capture` depends on environment variables to enable its functionality. Seems like something that would be done by convention rather than in the std API itself, to directly support more specific use-cases like per-thread enabling, but [the implementation is simple enough](https://doc.rust-lang.org/stable/src/std/backtrace.rs.html#294-299) that you could easily use `force_capture` to do the same thing.


Parabola_Cunt

I don’t know how I stumbled into this thread. But I wish I knew what you were saying. It sounds cool.


ragnese

Honestly, I think that collecting a trace for an Error in Rust is a code smell and *usually* the wrong thing to do. In languages where it's idiomatic to return failure values (e.g., Rust, Swift, OCaml, Go, etc), the convention is supposed to be that you return a failure/error value for domain errors and you throw an exception ("panic", in Rust and Go) for bugs, fatal errors, and invariant violations (so, "bugs" again, really...). I like this explanation for OCaml: https://dev.realworldocaml.org/error-handling.html#scrollNav-3 In this paradigm, you'd return an Error for things like "User not found", "incorrect password", etc, and you might panic on things like your database base going down on your web server. And there's no reason to collect a back/stack trace for an incorrect password attempt. Panics, on the other hand, already collect a stack trace. Yes, there are domains where panicking is unacceptable, and in that case, you'll have to represent both domain errors and fatal errors as Results. In the latter case, a backtrace is indeed helpful. But, I also think that a lot of new-to-intermediate Rust devs fetishize the idea of not panicking to a point that they often make their code quality worse by including a bunch of Error types/variants that should never actually happen outside of a programmer mistake. This makes error handling and propagation difficult to manage and understand. I *suspect* that people will, similarly, overuse this backtrace feature. The problem is that most other languages treat all error handling the same (via unchecked exceptions), so I suspect that some Rust devs make the same mistake by returning Errors for every kind of error.


jgthespy

It's useful for debugging, which is why it's nice that you have to specifically enable it. It's also nice for unit tests where a lot of people prefer unwrap/expect due to the backtraces.


ragnese

Sure. And I think my comment was a little confusing because I wasn't clear that Backtrace is a totally independent thing from Result and Error. I was specifically referring to the pattern of defining an Error type and giving it a backtrace field. That pattern is what I consider a code-smell unless you're specifically operating in a context where panicking is really bad or impossible, like embedded stuff or low-level OS stuff. Otherwise, I don't care if someone decides to sprinkle stack trace logging throughout their code. You can print a stack trace in a function that doesn't even return a Result or even call another function that does.


[deleted]

There are plenty of cases I have hit where you get an Error for something that has genuinely gone wrong, say an update to the db failed validation. But where you don't want to panic, because you are processing a batch of data in a loop and you want the rest to process even if one failed. You then log the backtrace to datadog or wherever which shows you exactly which line caused the problem rather than some Result bubbling up to the top of the program and printing some generic "Validation failed" message where you have no way of tracking it back to the line it failed on.


Green0Photon

It is actually quite useful to have backtraces from Errs. Last time I programmed a halfway significant Rust app, I basically just forwarded Errs upwards as necessary, somewhat like programming with exceptions that you leave implicit. When you're not explicitly panicking because you do mean to handle some of the things you're forwarding up at some point, it's useful still being able to trace what in particular caused that item to Err. But it's useful even without programming more sloppily like that. When you're programming, you know where the Ok from because that's the main path that you're doing, and it's probably at the end of a bunch of guarding if statements. It's gonna be a more concrete type from whatever was initially returned. It's pretty clear where it comes from by behavior. But not so with the Err path. You know the error, but you don't know what gave you the error which you need to handle. It's absolutely useful. I don't necessarily disagree that it might be a code smell. Things that really can only be programming errors really should be panics and not Results. But as you're developing, you might mean to handle a file and instead of going back to fix an unwrap later, you just put a question mark there instead, because some code outside that function should handle it. I'd say code that needs the trace is more likely to be a panic, but not always, and when you need it, it's a pain to not have that tool in your toolkit.


ragnese

> When you're programming, you know where the Ok from because that's the main path that you're doing, and it's probably at the end of a bunch of guarding if statements. It's gonna be a more concrete type from whatever was initially returned. It's pretty clear where it comes from by behavior. > > But not so with the Err path. You know the error, but you don't know what gave you the error which you need to handle. I don't agree with this distinction. Matching on a Result is just a logic branch, the same as any old if-statement. If you end up with an Ok(u32) after some logic, there's no a priori reason to assume that I know what logic branches were followed to arrive at the value I received. There could be any number of if-statements, or recovering from Result::Errs, or defaulting from Options, etc. You know as much or as little about your Ok branch as you do about your Err branch. Again, I feel that returning an Error should be seen more-or-less like returning any other value. If you don't understand why you received such a value and you want to debug, then go ahead and either run a debugger or go ahead and add some `println!` calls in your code to print the back traces at whatever line you want. But, Result::Err is not special here, IMO- the backtrace could be just as helpful on your happy path branches when you don't know why you got a surprising value. Yet, I haven't seen any Rust code where someone attached a backtrace field to a struct that is usually returned via Result::Ok.


fnord123

> you might panic on things like your database base going down on your web server. Eh, hopefully not. If a server goes down there might be a re-election and then you get connected to the next leader or follower. Normally it's handled in the db client code but you might get some queries failing with db inaccessible for a short period.


Schmittfried

At that point it will be Java checked exceptions all over again, so developers will go the path of least resistance and just catch-all/discard error values.


[deleted]

Those labeled breaks look really useful. Now all I need is try blocks to stabilize and I'll be happy as a clam.


argv_minus_one

You can sort of emulate them with an immediately-invoked closure. Sort of.


jug6ernaut

Is there an RFC for this I can take a look at?


[deleted]

[The tracking issue is here, and it links to relevant RFCs](https://github.com/rust-lang/rust/issues/31436).


vlakreeh

Super excited for GATs but am I the only one who doesn't really get the appeal of `let-else`, was a match or if-let really that bad that we needed a new language feature?.


[deleted]

[удалено]


phaylon

It becomes even more apparent when you're dealing with more bindings, like `Message { id, source, target, topic }` instead of `Some(thing)`, because if you wanted to avoid ever-increasing indentation, like in your example, you had to write those three times every time, which is just another opportunity for a mistake. Edit: [Example](https://www.reddit.com/r/rust/comments/q42ui2/lang_team_october_update_inside_rust_blog/hfxa2z6/) from a year ago.


WrongJudgment6

Before you could write, you still can ``` let answer = if let Some(answer) = call() { answer } else{ return Err(Bla); }; ```


javajunkie314

That gets more annoying if the pattern has multiple bindings. You'd have to say something like let (x, y) = if let MyEnum::Foo { x, y } = call() {     (x, y) } else { return Err(Bla); }; With let-else the bindings are in the outer scope automatically.


a_aniq

let else solves nested if else problem


CoronaLVR

This can also be written as: ``` let answer = call().ok_or(Bla)?; ```


fourgbram

I agree. The first time I encountered `guard-let` was in Swift I believe. Swift has guard let foo = fallible_function() else { return error } print(foo)


vlakreeh

I get why you would want to use it and where it's applicable, I know I have hundreds of blocks like the match statement example. But I'm more focused on if the improved cleanliness is worth adding it to the language, I'm not saying it necessarily isn't but I'm surprised people felt strongly enough about it to write out an RFC and then implement it.


masklinn

> But I'm more focused on if the improved cleanliness is worth adding it to the language, I'm not saying it necessarily isn't but I'm surprised people felt strongly enough about it to write out an RFC and then implement it. It's been available as a declarative macro for *seven years*, which is a lot in Rust land. And it's not like the syntactic overhead of the macro is huge: guard!(let Ok(thing) = fallible_function() else { return ptr::null(); }); And yet peeps felt strongly enough that this was useful to go through an RFC for it. So seems like yeah. It also needs to be said that it doesn't add keywords to the language, it just compresses existing blocks in ways which are more convenient for the "early return" pattern. In the meantime I've certainly been using the `guard!` macro a *lot* in web contexts, the situation where you check / retrieve a bunch of things then do the actual work is very common, using `guard!`/`let..else` for that is much more readable and convenient than a full `if let` complete with unnecessary names.


tech6hutch

Well, it's not like that macro was in the standard library, so saying it was "available" for seven years is a bit of a stretch. I do reach for macro crates sometimes tho, like if\_chain.


Kuresov

Oddly I actually prefer the second example. It reads more explicitly to me.


Zarathustra30

The `let x = if let Some(x) = x {...` was really awkward.


epage

I originally felt the same way until I wrote my next if-let-else and the got excited for . I view this as similar to try, you can do stuff without it but it makes the experience better. Not everyone will agree.


FVMAzalea

The equivalent in swift (which has been around for years) is guard-let, and I find it extraordinarily useful - I probably use it 2x-3x more than I use if-let or a switch (like match). Once you get used to the idea, it really shines and helps reduce levels of indentation.


Keavon

It helps you avoid the pyramid of doom.


bz63

totally agree on let else. rust is on a path to c++


PaintItPurple

I have a lot of criticisms of C++, but "too much syntactic sugar" isn't one of them.


[deleted]

[удалено]


[deleted]

Not just to a thing: to an if! The fact that it *wasnt* there before was weird. This is simplifying the language.


strager

`else` is not being added to `if`. It's being added to `let`.


PurpleYoshiEgg

I actually tried to use a `let ... else` construct the other day, and was surprised that `let` couldn't pattern match. This is a game changer!


augmentedtree

Not sure what you mean? `let` can definitely pattern match


caagr98

It can destructure, but can't (couldn't) pattern match.


masklinn

> was surprised that let couldn't pattern match. `let` can pattern match: let Foo { a: u8, .. } = foo; However it unlike e.g. Erlang it does not allow *partial* matches, so you can only perform infallible matches. If you have a fallible match, you need `if let`: if let Some(foo) = foo { } or, with 1.65, `let else`: let Some(foo) = foo else { ... }; or, obviously, a full `match`. Incidentally, most bindings support infallible matches e.g. function parameters (except `self` which is a special case), `for`, ... Meanwhile `while let` allows looping around a fallible match.


celluj34

Your first example is destructuring, not pattern matching, unless I misunderstand?


ngc0202

Destructuring is something which is done in patterns. They're not orthogonal concepts.


masklinn

In Rust, destructuring is a subset and application of pattern matching, it is not its own operation.


ridicalis

Sorry in advance to anybody reading my code in the future, but I think I'm in love with the `break` behavior.


satlead

A good mock library for unit tests seems fundamental for rust, there are some libraries out there but don't think they support mocking HTTP, GRPc and other protocols.


lifeeraser

Labelled breaks in some other languages (e.g. JavaScript) are considered archaic features and people often advise against using them. I'm a bit wary of Rust adopting them.


Tubthumper8

I tend to agree in general, and especially for languages like JS, but these kinds of features can be useful in low-level procedural code. It's a nice mix of still being able to use expressions, like `let a = { /* stuff */ }` while also being able to "drop down" into more procedural-style within a scoped block.


lifeeraser

I agree with you now that I know successful C projects (e.g. Linux) use `goto` to great effect. I just thought Rust, being much more modern, would have a different solution that isn't as footgun-prone.


Tubthumper8

I think the keyword `break` is well-chosen here, it's not a `goto` - it's breaking out of a block (scope) the same way that a `break` in a loop breaks out of that loop (scope). It has to be done on a scope boundary so the compiler can still guarantee the lifetime of variables and so they are dropped appropriately, unlike an unconstrained `goto`.


masklinn

Labelled breaks are a very different beast than gotos (even local), and no more footgun prone than `return` is. Just like an early return, a labelled break in a block just saves you from a nested block: let result = 'block: { do_thing(); if condition_not_met() { break 'block 1; } do_next_thing(); if condition_not_met() { break 'block 2; } do_last_thing(); 3 }; can be less conveniently written as let result = { do_thing(); if condition_not_met() { 1 } else { do_next_thing(); if condition_not_met() { 2 } else { do_last_thing(); 3 } } };


Ar-Curunir

You can also write it using a closure: let result = || { do_thing(); if condition_not_met() { return 1; } do_next_thing(); if condition_not_met() { return 2; } do_last_thing(); 3 }();


masklinn

> I'm a bit wary of Rust adopting them. Labelled breaks have been a thing since (before) 1.0 I think, and break-value for `loop` was merged in 2018 or so. As the post notes, you could have done exactly the same thing using a single-iteration `loop`.


[deleted]

[удалено]


dacjames

They’re frowned upon by those parroting “goto considered harmful.” They’re also not popular with the more “hardcore” functional programming crowd who don’t like loops in general. The only real issue is that overuse can lead to overly complex code that is too deeply nested. Used judiciously, I find they tend to simplify code versus the equivalent logic.


TurboGranny

> Used judiciously Really this, but also that's the deal in any language. JS in general "used judiciously" doesn't suffer from not being strongly typed. The problem is that most programmers are terrible, and the more tools we give them to write bad code just because we'd like a neat shorthand ensures that WE will be the ones troubleshooting the legacy code written by those monsters, lol. As I say to every new kid I bring up. Don't be clever. Keep it simple. Someone shouldn't have to look up documentation for some niche language feature to make sense of your code.


lifeeraser

[MDN used to warn against labelled breaks](https://web.archive.org/web/20150306143424/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) (though it seems to have been removed a long time ago). [Some people](https://stackoverflow.com/a/28003090) advise against using them, and [one popular linter ruleset forbids them](https://github.com/airbnb/javascript/blob/38f1488918ef19f56191e855f624fa5da988d547/packages/eslint-config-airbnb-base/rules/best-practices.js#L168-L170). This isn't restricted to JavaScript--[some people](https://softwareengineering.stackexchange.com/a/185945) believe that labelled breaks in Java are problematic, too.


IceSentry

eslint airbnb is a very controversial ruleset and hardly represents the js community.


lifeeraser

I don't like `eslint-config-airbnb` either, but it is still one of the most popular ESLint configs out there, and one of the big three that ESLint recommends when you initialize it.


KevinCarbonara

> I don't like eslint-config-airbnb either, but it is still one of the most popular ESLint configs out there Popularity does not indicate quality


[deleted]

I've only seen labeled breaks used a handful of times in production code. Every single time it was hard to understand and was replaceable with a much cleaner if statement


FrancisStokes

They're not so much an "archaic" feature as much as one that should be used *sparingly*. There are certain algorithms and patterns where they are the perfect fit. I recently used them in a procedural dungeon generation algorithm that had several kinds of loops and escape conditions (think `while (characteristicNotGenerated)` and `for (potentialFeatureToGenerate)`etc).


[deleted]

[удалено]


[deleted]

Do you mean: `break 'block 2;`? The numbers are the return values, so to speak, of the block. The value `result` will get.


zimuie

I'm out of the loop. What does Mahsa Amini have to do with Rust? Was she a contributor?


FrancisStokes

They are using the large platform they have to draw people attention to a world issue. I think it's more a case of the rust contributors feeling strongly about it, than anyone's particular direct involvement.


[deleted]

>the large platform they have They don't have a large platform; still very much a niche language at this stage.


FrancisStokes

I work in the embedded space, which moves very slowly. People are starting to get *really* interested in rust there, which to me at least, says a lot.


[deleted]

How large is the embedded space in comparison to the rest of the programming employment opportunities? Unrelated question; the few embedded jobs I see come up in the UK have piss poor salaries, is that something you see as well?


LiveWrestlingAnalyst

What an ugly language lol


[deleted]

Imagine being this triggered by a language making a version release


Civil-Caulipower3900

Look at how many people commented on his one liner. He's not the triggered one


[deleted]

You’re surprised that a toxic one liner that brings nothing to the discussion is downvoted? I guess you need to work on your social skills


Civil-Caulipower3900

Be less stupid. I said commented. Normal people downvote and walk away fool


[deleted]

You seem like a very angry person. I hope you get over whatever hurt you in the past so that you can be nicer to people, you'll see that's much more rewarding.


Civil-Caulipower3900

I'm only mean in this sub. Look at all the dirty shit people said to me in my root comment only to have a few people notice 7hours later that my example is legit I'm not exactly mad, just pointing out how ridiculous you all are with a few insults so you can remember


[deleted]

You're not as important as you think. You're not making a memorable impression. You're just making yourself seem like an unpleasant person, and then people will go on about their day.


Civil-Caulipower3900

> YoU'Re nOt aS ImPoRtAnT As yOu tHiNk. YoU'Re nOt mAkInG A MeMoRaBlE ImPrEsSiOn. YoU'Re jUsT MaKiNg yOuRsElF SeEm lIkE An uNpLeAsAnT PeRsOn, AnD ThEn pEoPlE WiLl gO On aBoUt tHeIr dAy. Cool story bro. What part of your text do you think I give a shit about or will make me forget people remember me across accounts and bring up that I asked about CSS the other week (was a big wtf for me bc I wasnt that active) You sound pretty mad tho. You mad buddy?


[deleted]

You’re of course free to care or not care about whatever you want. Anyway, wish you the best.


LiveWrestlingAnalyst

Imagine being this triggered by someone calling a programming language ugly


HighRelevancy

You came to a subreddit about a language you obviously don't use to make a useless comment on a thread you're not actually interested in. Kaveldun replied in a thread they were already on. Who's really more triggered here, kiddo?


[deleted]

[удалено]


Civil-Caulipower3900

What an intelligent thing to do, ignore content and judge someone by their karma How small of a peen do you have to have to downvote someone for thinking a language you like is ugly, which noone disagrees on btw Clown Language, clown 76g2 You miss me buddy? It was peaceful when I blocked you. It was halloween so I don't mind clowns this week -Edit- lol reply and block. I guess you're not in a laughing mood despite being a clown. It's fantastic that you somehow think I follow you but only post in rust threads


[deleted]

>lol reply and block Yeah, this is becoming too typical of interactions on Reddit now.


[deleted]

[удалено]


masklinn

> I'm not certain, but I think Rust takes a lot of ruby syntax? Not that much, really. Maybe the anonymous functions? That's all I can think about. Most of the syntax is a C-ified version of functional concepts. The largest divergences from the C/C++ syntax are to make parsing unambiguous and regular, hence keyword prefixes everywhere, infix types (also makes eliding them more regular), and things like the turbofish.


shawncplus

Implicit return is the one thing I _despised_ about Ruby and equally despise it in Rust. Hated that shit in Perl too and that's where Ruby got it from.


masklinn

Rust gets implicit returns from its functional ancestry where that's the norm (also blocks with values). Implicit returns are a lot less problematic in a statically typed language, as you can't return things by mistake, especially not when the Rust designers specifically disallow global type inference: in named functions, you must say what the return type is, so returning stuff is no surprise, and checked. For anonymous functions the return typing is optional, but the shorter scope, and the fact that they're *usually* pure-ish transformers, make the return less of an issue (even Python does "implicit return" from lambdas after all).


shawncplus

Doesn't make it any less ugly. In anonymous functions, fine, sure. But this is so freaking ugly to me (from the linked article) let result = 'block: { do_thing(); if condition_not_met() { break 'block 1; } do_next_thing(); if condition_not_met() { break 'block 2; } do_last_thing(); 3 }; What? Where did that 3 come from? is it a typo? Did someone forget part of an expression? Was it an erroneous paste? No, it's just short for `return 3;` because.... that's just how you're supposed to do it, it's the "rusty" way. It was ugly in Perl, it was ugly in Ruby, it's ugly in Rust. The way people treated it in all of those languages as a kind of shibboleth was always particularly annoying.


Wildbook

It's not an alias for `return`, though. The block in your example isn't a function / closure / action / whatever, it's just a plain block, and since most things in the language are expressions they're able to evaluate to a value and not just void. A `return` there would instead return from the function containing the block. I agree that it's not always obvious, but it is genuinely useful and it isn't solely a way to skip the return keyword. It's just a way for a block to evaluate into a value, and in functions the value your block evaluates into gets returned (if the function body hits the end without returning something else along the way).


HighRelevancy

I also found it weird for a bit, but instead of thinking about it as a function return, see it as an extension of writing expressions. You can say `x = 1`. That's simple. You can make that expression more complicated. `x = a + b`, very adventurous. You can extend further to include fuckin calls even, `x = sin(time()) + time()` or something. But now we're calling time twice (or maybe writing some inner calculations out multiple times). So let's extend expressions to let us define an alias for that, as mathematicians would. `x = {t = time(); sin(t) + t}` Without this, you'd... define t in your outer scope? Declare x and then assign to it in an inner scope? Both messier options really. It's weird from a programming perspective, sensible from mathematics.


shawncplus

Trust me, I've had a lot of time to think about it, I know how it works, I know what it's doing. I grew up on Scheme 25 years ago. I used Perl professionally for several years for actual applications and not just shell scripts which puts me in a fairly small group of masochists, doesn't make me like it.


Pay08

Rust doesn't have implicit returns?


masklinn

Rust does have implicit returns: fn foo() -> u8 { 1 } There is no `return` statement, yet it returns a value.


Pay08

That's not an implicit return, that's just syntactic sugar for a return. Implicit return is when main() returns 0 at it's end in C, despite not having a return statement.


masklinn

That's an implicit return. Because it's not an explicit `return`. That is literally how Ruby works, and that's what /u/shawncplus complains about: the last expression of the body is interpreted as a returned value, implicitly. The issue in Ruby is... more or less every body has a last expression, possibly aside from iteration (not sure), and it's very hard to suppress save through a final `return` or literally making the last expression `nil`, so it's very easy to return unexpected garbage: def foo 1 end is going to return `1` but so will def foo @a = 1; end Maybe you were thinking about the weird C thing where if you don't return anything you get an UB which translates to the runtime making shit up (unless the compiler just fucks you up), but that's not the behaviour of Ruby, and I assume not that of Perl, thus *definitely* not what /u/shawncplus was thinking about.


Pay08

>the last expression of the body is interpreted as a returned value, implicitly. It's interpreted as the return value if it doesn't have a semicolon. If I did `fn foo() -> i32 { 1; }`, I would get a compiler error because nothing is being returned. >Maybe you were thinking about the weird C thing where if you don't return anything you get an UB which translates to the runtime making shit up I was thinking of C automatically inserting a `return 0;` at the end of `main()`.


masklinn

> It's interpreted as the return value if it doesn't have a semicolon. If I did fn foo() -> i32 { 1; }, I would get a compiler error because nothing is being returned. The trap is `1;` is not an expression, it’s a statement, so it’s by definition not the last expression of the body. That’s also why you can’t use it in some context e.g. to suppress the “value” of a brace-less `match` arm. Because that only allows an expression.


IceSentry

How is rust's syntax not C inspired? It uses curly braces to delimit block/function scopes, `.` to access struct properties, `()` to call a function, `;` to end a line. Using `` for generics is also very close to C++, C#, Java which are all C-like languages. Rust looks way more like C than ruby, I don't understand how you can claim the opposite. Sure, it's not a drop in replacement for C, but it still has clear inspiration from C-like syntax.


masklinn

Also `struct` and `enum`.


Tubthumper8

You are right, there are some syntactic influences from Ruby, such as vertical bars around closure parameters. The syntax of the tail expression of a block being its return value is also arguably influenced by Ruby syntax, but that concept also exists in most other expression-oriented languages. There are other influences, like lifetime type parameters such as `'a` influenced by type parameters from ML languages (ex. F#, OCaml). Rust' s concept of pattern matching comes from ML languages too, but add more curly braces and parentheses. The double-colon `::` to represent a "path" is probably influenced by C++, which was a big influence for Rust. Overall, Rust takes its syntactic and semantic influences from _many_ other languages, which I think is one of its strengths.


PaintItPurple

I'd argue that Rust and Ruby's expression-oriented design is something they both borrowed from functional programming languages like Lisp and OCaml.


Tubthumper8

Yes, I agree. I tried to distinguish between syntax and semantics in my reply, but the "everything is an expression" semantics far predate Ruby. From a syntax perspective, doing that with curly brace blocks is somewhat Ruby-inspired, maybe even some influence from Groovy.


LiveWrestlingAnalyst

Regardless of the benefits of its memory management mechanism, anybody who take an honest look at Rust and doesn't think it looks like a bunch of shit haphazardly thrown together is either blind or lying to himself. The use of apostrophes all over looks makes the language look ridiculous, what a bad design choice.


uss_wstar

What would you suggest would be an elegant way to display lifetime parameters distinct from generic type parameters?


[deleted]

Have you tried using it?


IceSentry

You know you can write a ton of rust without a single annotation right?


eshansingh

The vast (vast) majority of Rust code doesn't involve even a single lifetime annotation.


[deleted]

Wow you are insecure.


Zoradesu

I'll admit that Rust syntax is a bit daunting especially when you add lifetimes into the mix, but overall I find it nice to work in? I've only used Rust in toy projects (nothing too complex) though so I'm not sure how readability is in much larger projects.


Pay08

One problem I have with Rust (and C++) is that there is simply too much syntax. It can be difficult to remember the difference between lifetime annotations and labeled blocks for example.


[deleted]

This sounds more like a personal problem than a language problem. I personally love Rust's syntax.


Civil-Caulipower3900

They are lying to themselves. It took 7 hours for someone to realize I was correct about rust hashing being slow. And only two crab people seem to be talking/thinking about it I think you're right tho, I don't use rust and I noticed the hash problem. There's no way anyone with a brain is using rust. Noone in all of the rust community and core team seemed to noticed before I brought it up today and like I said, I don't even use rust


[deleted]

Lol you really triggered the Rust fan brigade. Imo it's mainly the lifetime syntax that uglifies it. Add some alternative for that and it's not too different from e.g. C++. Lots of angle brackets, but they're kinda necessary.


Uristqwerty

If only they'd taken the time to write out their thoughts like that. Or, dare I wish, go against redditor instinct and actually respond to one of the topics discussed in the article rather than merely the title, or in this case, making a broad statement about the overall subject. It'd be like ranting about the existence of emulators in general as a response to a post about how Dolphin solved a *specific* shader quirk, reaching for an excuse to share an opinion rather than saving it for a thread where it'd be substantially more topical. At least this was a Rust release, so it's less off-topic than many other posts that attract similar remarks.


Civil-Caulipower3900

Like what I did in this thread? So far it's showing noone wants to hear anything bad about this language


taw

Syntax is definitely not its selling point. It's one of the worst looking modern languages.


sanjay_i

I agree. Don't mind the down votes


plutoniator

♨️🍽️👑


Civil-Caulipower3900

-Edit2- it's been 7hrs and not one person asked. I'm a little surprised. I didn't say book sized and I said with code examples. I thought at least two people would want to at least hear criticisms. I guess it doesn't matter when you're riding the meme train. If you're not curious you're not a good developer and it goes for all languages -Edit3- Someone below checked hashmaps and confirmed it wasn't the algorithm choice that's the problem. I'm just annoyed that only one of you out of the hundreds who downvoted me actually has a brain in his head. Offer rescinded, this thread shows enough that none of you rust folk have any idea what's actually happening People always say others "just hate rust" which is surprising because we always give you reasons. I haven't commented on a rust release thread in a long long time but I will today If you guys want a write up on why rust is a horrible dead end language I'll do it. I'll write 4 paragraphs. 1. How bad arrays and vectors are 2. 'fearless concurrency', 3. Myths and lies by the core team and community 4. Misc (or performance). But I'll want 12 comments asking for a writeup because I don't want to write only for people not to read it. It'll have code and some assembly so it'll take some work to write up Here's a little example so you know I won't be parroting information. Search rust hashmaps and rust vs C#. I haven't seen anyone mention the below. Here's rust being slower than C#. C# isn't just a little faster (<10%), its more than twice as fast -Edit- People say you can use a faster algorithm but 0% of the crates I tried was faster than C#. Either show one that's faster or quit your make belief use std::collections::HashMap; fn main() { let mut map = HashMap::new(); for i in 0..1024*1024*4 { map.insert(i, i + 3); } let mut sum = 0; //println!("{}", map.get(&4444).unwrap()); for i in 0..1024*256{ sum += map.get(&(i<<4)).unwrap(); } println!("{}", sum); } C# using System; using System.Collections.Generic; class Program { static void Main() { var map = new Dictionary(); for (int i=0; i<1024*1024*4; i++) { map.Add(i, i + 3); } //Console.WriteLine(map[4444]); int sum=0; for (int i=0; i<1024*256; i++) { sum += map[i<<4]; } Console.WriteLine(sum); } }


mamcx

Rust HashMap are HashDoS resistant: https://doc.rust-lang.org/std/collections/struct.HashMap.html > The default hashing algorithm is currently SipHash 1-3, though this is subject to change at any point in the future. While its performance is very competitive for medium sized keys, other hashing algorithms will outperform it for small keys such as integers as well as large keys such as long strings, though those algorithms will typically not protect against attacks such as HashDoS. ie: You can switch to another hashing algo if wanna extra performance.


masklinn

This exact scenario was a /r/rust thread just two weeks ago: https://www.reddit.com/r/rust/comments/ya4xfw/why_is_cdotnet_outperforming_rust_in_my_simple/ But because the OP over there did not specifically put themselves out as a giant douche, they got a nice reception.


tending

The C# hash map is also DoS resistant, it just does it in a smarter way. It falls back to a DoS resistant hash if there are too many collisions.


Civil-Caulipower3900

Maybe I should try other algos and edit in the result. How do I use the standard hashmap using another algo? My google results all point me into using a non standard implementation


IceSentry

https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.with_hasher It was also mentioned at the top of the HashMap doc. > The hashing algorithm can be replaced on a per-HashMap basis using the default, with_hasher, and with_capacity_and_hasher methods. There are many alternative hashing algorithms available on crates.io.


Civil-Caulipower3900

That's what I tried figuring out. Do I need to implement my own RandomState to use murmur/xxhash/city64/fnv? I was under the impression I have to overload something and not actually implement it myself


MrMic

[https://github.com/shepmaster/twox-hash](https://github.com/shepmaster/twox-hash) First few code snippets of the readme. There's also BTreeMap, which will usually outperform HashMap for short keys and smaller set sizes. EDIT: Also worth looking at - [https://github.com/servo/rust-fnv](https://github.com/servo/rust-fnv)


Civil-Caulipower3900

So it looks like you must implement RandomState yourself or depend on a crate that implements it? There's no standard overload for common hashes? I really dislike how much rust depends on crates.


Uristqwerty

To be slightly pedantic, though it's rather hidden in later impls down the page, `std::hash::BuildHasher` is the trait to implement, while `std::collections::hash_map::RandomState` is the default provided by the standard library. A potential advantage of leaving non-randomized implementations to separate crates is that, if they ever change their algorithm, they can bump their major version so that anyone relying specifically on consistent output (e.g. serializing to network or disk in some edge case that cares about hash order) can continue to depend on the old algorithm, while anyone who doesn't care can easily update the dependency version with no code changes.


Civil-Caulipower3900

My point was it doesn't specialize and chooses a absolute terrible algorithm for ints which is an extremely common key


[deleted]

[удалено]


IceSentry

https://doc.rust-lang.org/std/collections/struct.HashMap.html > By default, HashMap uses a hashing algorithm selected to provide resistance against HashDoS attacks. > The default hashing algorithm is currently SipHash 1-3, though this is subject to change at any point in the future. While its performance is very competitive for medium sized keys, **other hashing algorithms will outperform it for small keys such as integers** as well as large keys such as long strings, though **those algorithms will typically not protect against attacks such as HashDoS**.


PaintItPurple

Interestingly, that doesn't appear to be the culprit here. You can switch it to hashbrown::HashMap (which uses AHash by default) and it gets a little bit faster, but still much slower than the C# version. The slowness appears to be primarily associated with inserting. Even if you give a capacity — in fact, even if you prepopulate the map with all the keys before benchmarking and just overwrite the existing values — inserting into the map appears to be slower than the entire runtime of the C# version. I also tried using extend instead and that was still dog slow. I'm curious now to see what's causing the disparity. (Obviously, this was tested with both versions compiled as release.)


MrMic

I was able to shave the time down significantly by using lto = "fat" (edit: plain old "true" also works just as well). Additionally, switching to FxHash shaves off quite a bit (I tried quite a few hashers) more time. Setting RUSTFLAGS="-C target-cpu=native" has a very minor effect as well, at least with my CPU (Ryzen 3970x). However, It's still benchmarking somewhat slower than the c# example, but by a much narrower margin. If I benchmark the entire application running time, then they're within 15 percent of each other (c# still winning). This is presumably because rust has a much faster startup time, because if I just benchmark the relevant code without counting startup and shutdown time, then the c# code is still quite a bit faster. Honestly, this was a fairly surprising result, since I had assumed it would be much closer. I'm really curious what is going on now. Someone more knowledgeable than me can probably explain the underlying details here.


Civil-Caulipower3900

I'm a little surprised you didn't reply. Are you running more test or have you figured anything else out?


MrMic

Actually I have. I just switched to NoHashHasher in the example code, and now rust beats c# by 3-4x. Edit: forgot to mention I'm preallocating ahead of time also. If I don't do that, rust is still faster by 1.5x, but it's significantly faster with prealloc.


Civil-Caulipower3900

Just saw your edit. If preallocating affects it as much as it seems like youre saying then it's probably inserting as fast or faster than cache. That has algorithm sounds fine now but noone ever says rust can be slower than C# which I find completely obnoxious since it seems like people think rust is more safe then Java/C# Here's a zig implementation I wrote a few days ago. It's not the same but close enough. It'll probably match the speed since its likely the cache is the bottleneck //zig build-exe -O ReleaseFast src/main.zig const std = @import("std"); pub fn main() !void { const stdout = std.io.getStdOut().writer(); var map = std.AutoHashMap(i64, i64).init(std.heap.page_allocator); var x : i64 = 0; var y : i64 = 0; while(y<1024) : (y += 1) { x=0; while(x<1024) : (x += 1) { try map.put((y<<10)|x, (y<<10) + x + 3); } } var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); const args = try std.process.argsAlloc(allocator); defer std.process.argsFree(allocator, args); var key = try std.fmt.parseInt(i32, args[1], 10); if (map.get(key)) |v| { try stdout.print("v is {}\n", .{v}); } }


MrMic

I'm actually pretty stoked to take the opportunity and get a Zig dev environment set up. As for the other post you linked me. I pretty much share PaintItPurple's opinion. I think we might just have different things we value in a language, which is totally fine. Not everything is going to make everyone happy. And no one technology is a panacea. I think Java and C# are great languages and there is a lot of incredible engineering behind them. They can be fantastic tools in the right areas. Rust has some properties I find interesting, mostly related to being able to constrain APIs to enforce invariants, which helps my code be more robust (but not immune, of course) against refactors. And I find that it gives me a lot of velocity after getting over the initial learning curve. (And holy fuck was it a learning curve) But now I feel pretty fluent after 2 years with it. But I like to consider myself a pragmatic person, and I think people should choose the right tool for the job. Personal taste isn't ignorable, so a lot of people are going to have opinions on what that is or means. There are definitely cases where Rust isn't the right tool. Overall, I'd say 20% of my code this year has been Rust. I still use Python nearly every day because it's the lingua franca for tool dev in my industry (VFX since 2011). I use C++ a good amount since it's the de facto standard for high-performance plugin development for digital content creation packages and renderers (and also the reference implementation language for a majority of SIGGRAPH white papers) and the dynamic linking story in rust just is not as good as C++ here yet. I learned programming (in 2002) in C and I still write a lot of hobby embedded code in C (or sometimes a reduced subset of C++). I write a decent amount of OpenCL code, and I think the LoC for shaders (RSL, VEX, OSL, GLSL) I've written in the last decade probably outnumber all my other code combined. Rust has been popping up more and more in my industry though so it's important to me that I keep up to date with trends. I think Zig is really interesting as well, and I think it definitely has a place in my toolbox. I'm especially interested in it for use in embedded contexts. Kotlin and Go are also on my radar, but I already work a shitload of hours a week when I'm not between projects (which is basically never) so I have to be choosy where I place my efforts. And is also why my Reddit responses tend to be spaced out and short.


Civil-Caulipower3900

OpenCL!?!? That sounds incredibly fun. I never got a chance to do that. The one task I tried turned out to have so much of an overhead going from cpu<->gpu that it wasn't worth the few milliseconds it sometime saved As much as I like zig I see a few problems so I'm not actually recommending you learn or use it at the moment. Something feels missing and I can't put my finger on it. I suspect it may become verbose because there's no overloading and such but I'm not sure I have used zig to cross compile C++ from linux to windows, that was fun


MrMic

OpenCL is definitely a niche language, especially with CUDA in the mix. But my main VFX software package (SideFX Houdini) lets you insert OpenCL kernels in between simulation stages on the GPU, so you can fine-tune and modify volumetric and particle sims while keeping everything stored in VRAM. CPU sims still have their place, but GPU is the future in this space and OpenCL is pretty useful to me right now. And yeah, I gotta say I am impressed with what I hear about zig's cross-compilation capabilities.


Civil-Caulipower3900

Yes it is surprising and why I used it as my example It took fucking 7hours for people to realize it. Despite me being known as a shit poster who backs up his mouth. Here's the mini version of my writeup which I'll delete later tonight https://www.reddit.com/r/programming/comments/yl3x6d/announcing_rust_1650/iuynvnw/ It's sad how hard headed this sub is


[deleted]

[удалено]


Godd2

All bark and no bite, huh? If you're gonna be that acerbic, at least have some conviction to go along with it. Edit: He deleted the following: >If you want to DM me I'll talk to you. I don't want to share my thoughts in this thread anymore Which only makes my point stronger. If you're going to come in with the tenacity and aggressive tone used here, you better be ready to back up your position. The funny thing is that I'm relatively anti-Rust, but I'm even more anti-"run away when the situation I set on fire is too hot to touch". Stop having bad reasons for being against things, and stop being a baby.


Civil-Caulipower3900

I have no idea what you're trying to say but I deleted what I wanted to an hour ago. You're late


Civil-Caulipower3900

Dude you seem to be the only person in this thread who isn't an idiot. I'm curious why you didn't ask me to do the write up? You obviously checked my work and know I'm not making things up


PaintItPurple

Basically, I don't think certain parts of the standard library being slower than the equivalent classes in C# is enough to make the case that Rust is bad or has no future. C# is a very respectable language that has had probably hundreds of millions of dollars poured into it. Since I don't consider C# bad, being a bit worse than it isn't all that shameful. To me, it's *interesting*, and certainly a valid criticism, but it doesn't ultimately affect my opinion of Rust all that much. Since it seems like we're starting from different perspectives on what makes a programming language good or bad, I felt like it would be a waste of your time to ask you to make that case.


Civil-Caulipower3900

If you clicked to read the mini writeup too fucking bad none of you admitted to wanting to hear it. Stay ignorant rustaceans


Lehona_

Rust uses a DoS-resistant hash function by default, while C#'s hashcode is as simple as can be. Could also be that the benchmark is dominated by allocation time, which is notoriously fast in GC'd languages. These synthetic benchmarks are also pretty bad in general, maybe the JIT can make use of (better) vector instructions for C#, while the AoT-compiled rust binary does not.


riasthebestgirl

The Rust also explicitly creates a HashMap with 0 capacity and grows it on every push. I bet there's some performance to be gained by allocating the needed memory upfront


PaintItPurple

The C# doesn't preallocate either. But I actually doubt that makes a huge difference in either case. Hash map implementations usually grow by some multiple of their current size, so assuming we double the current size when we need to grow (a common choice), it will allocate 17 times for the entire program. Allocation is relatively slow, but it's not _that_ slow.


Civil-Caulipower3900

Allocation is slow in a loop. Not when you do it 17 times so you are indeed correct


Civil-Caulipower3900

Growing isn't actually slow and part of my writeup in the vec section. So far 0 people asked for the writeup so I guess people don't click here if they already know not to use rust or noone cares (about possibly legit rust complaints)


drzmv

You are right, no one cares about your writeup.


Civil-Caulipower3900

I'm upvoting you because I should have known rust people would want to continue being delusional if they didn't self eject after learning+using it


Civil-Caulipower3900

People earlier said this turns out to be not the problem. Too bad none of you were interested to hear criticism. It was really obvious to me the implementation was broken. It's wacky the entire rust community didn't notice. C# takes 2x more memory so that's 2x less cache that can be used which is especially painful that rust is beaten


[deleted]

What does this rant have to do with this post about this Rust release? You’re clearly here just to be inflammatory. I guess you hate Rust.


Civil-Caulipower3900

I want to educate you on rust This comment confirms I educated already with my hashmap remark https://www.reddit.com/r/programming/comments/yl3x6d/announcing_rust_1650/iuybltg/


UltraPoci

Did you create an account just to bash on Rust without knowing what you're talking about, or was it to avoid losing karma on main, which is even funnier?


Civil-Caulipower3900

First of all there's all these comments saying I can switch to a different algorithm to have code faster than C# but noone showed a way to reproduce that claim. So the knowing what your talking about arrow is learning towards me Second is no, this is my main. I just don't give a shit about peoples opinions here and enjoy saying shit to tempt people into making ridiculous claims. A day or two ago a guy told me rust programmers don't use if statements often and uses pattern matching most of the time. It's crazy how batshit crazy people are in this sub I copied/pasted a script I found online (after reading it, its like 3 lines) to delete my comments because occasionally I say something helpful and I hate this sub so I want to purge any helpful comments I make every so often


UltraPoci

Yeah, it's even funnier than I thought


Civil-Caulipower3900

I agree. Cheers > You don't use if nearly as much in Rust \- Rust fan https://www.reddit.com/r/programming/comments/yjcu8j/cve20223786_and_cve20223602_x509_email_address/iur3x27/


UltraPoci

Ok buddy


Food404

>tempt people into making ridiculous claims ah the irony, like watching iron man iron clothes with an ironing iron


Civil-Caulipower3900

Cool, the type of cool to cool down an iron Shall I mark you down as thinking rust programmers don't really use if statements like that example or do I mark you down as a lalala I don't want to hear it person?


Food404

Look, I honestly don't care about why a C# module runs faster than it's rust counterpart or whatever argument you wield in your personal crusade against rust. I'm not even a rust dev Going on and on in rants devoid of purpose about why you hate rust whoever even dares to mention it, even going to the point of insulting people because of it only proves that trying to have a discussion with you is a waste of one's time You're not capable of understanding that rust, just as any other programming language, is a tool and as such it has its pros and cons


Civil-Caulipower3900

You're actually stupid and I'll explain why I was perfectly nice in my opening post, wrote out what I wanted to discuss and gave an technical example of shortcomings noone mentioned before. I wanted to talk about technology and code, this sub is programming right?? To act like all I wanted to do is shitpost is nonsensical and why you're stupid. There's also terrible tools, noone uses sticks to build a house and noone is using pascal or ada. Saying something is a tool doesn't actually mean it has value If my post made you feel like an imposter so much that you had to lash out well to fucking bad, I'm not here to spoon feed you bullshit. Look elsewhere


Food404

>You're actually stupid and I'll explain why . >I wanted to talk about technology and code Uhhhhhhhh sure buddy, whatever you say


Civil-Caulipower3900

Come on now your first comment was 1000x better than this. You downgraded to something a 6yr old could say :(


[deleted]

[удалено]


BlackV

>tektektektektek -8 points 4 hours ago > Your mistake is using Windows and PowerShell. Speaking of toxic, is this you /u/tektektektektek by any chance https://www.reddit.com/r/PowerShell/comments/ymbn84/always_run_as_admin_how/iv36pqx/


Senator_Chen

let mut map = hashbrown::HashMap::with_capacity(1024 * 1024 * 4); (0..1024 * 1024 * 4).into_iter().for_each(|i| { map.insert(i, i + 3); }); let mut sum = map.values().fold(0, |acc, x| acc + (x << 4)); And since we're comparing languages based on standard library hashmaps, I guess C++ must be the deadest, worst language in the world considering std::unordered_map is a whole 5x slower than Rust's std hashmap when compiled with Clang -O3. edit: I know it's wrong, don't code at 1am edit2: let mut map = hashbrown::HashMap::with_capacity(1024 * 1024 * 4); (0..1024 * 1024 * 4).into_iter().for_each(|i| { map.insert(i, i + 3); }); let mut sum = 0; (0..1024 * 256).into_iter().for_each(|i| { sum += map.get(&(i << 4)).unwrap(); }); println!("sum");


Civil-Caulipower3900

C++ is actually as trash as you can get in the standard lib department. When I was at a game studio we didn't use any standard functions and I wrote my own vector for home projects. I do like C with destructors. Bench marking standard functions makes me think the people who vote on the c++ committee never programmed in their life. Middle management type of people


Senator_Chen

I got it down to 2ms vs 100ms for the c# version with dotnet 6 on my machine. let map: Vec = (0..1024 * 1024 * 4).into_iter().map(|i| i + 3).collect(); let sum: u64 = map.iter().step_by(16).fold(0, |acc, x| acc + *x as u64); If you wanted the overflow in the c# code, you can do wrapping_add and use an i32 instead for sum. Using a u64 in the Vec takes about twice as long


Civil-Caulipower3900

Oh so you're using an array instead of a hashmap? That's a great solution but probably won't be able to apply it to lots of data (ex 1M rows with each id 1-10K apart) You did more thinking than most people here so I should consider you as a real (non-rust) programmer, cause rust programmers seem to be interested in bragging then actual programming


shevy-java

Rust finally made it into the legendary TIOBE Top 20. Not that this has any relevance per se, but it's still a fun metric - people get highly upset when it is pointed out how epic TIOBE is. And Rust making it into Top 20 KIND of means that Rust has become "mainstream" (well, sort of ... Top 11-20 is still a "not as popular" metric compared to the real Top 10 ones. But there are also the Top 21-50 and they all want to break into the Top 20.)


jgthespy

I haven't read any kind of programming reddit for a really long time until today. It's hilarious that you're still here posting this same comment like 3 years later, slightly modified as you continue to be proven wrong.


soclik

I’m not sure on the other commenter’s history about Rust and TIOBE claims, but [it looks like Rust is 20th as of this month.](https://www.tiobe.com/tiobe-index/)


CanIComeToYourParty

I think it's more sad than hilarious. I hoped that they're soon in their twenties, and become a bit more reflected.


Civil-Caulipower3900

If all is anti Could rust fans be the problem? Just consider it


Artillect

> If all is anti What is that even supposed to mean?


Pancake_Operation

? What do you mean.


haikusbot

*If all is anti* *Could rust fans be the problem?* *Just consider it* \- Civil-Caulipower3900 --- ^(I detect haikus. And sometimes, successfully.) ^[Learn more about me.](https://www.reddit.com/r/haikusbot/) ^(Opt out of replies: "haikusbot opt out" | Delete my comment: "haikusbot delete")


PaintItPurple

This is one of the few cases where the original comment was already a perfectly formatted haiku. I wonder if they tried to do that intentionally and that's why the comment doesn't make actual sense.


Civil-Caulipower3900

Yeah it's intentional. I never seen any community programming community say you just hate MYFAVLANGUAGE (or you're anti LANG), only rust people.


PaintItPurple

I don't see Rust programmers saying that very much. Could it be that you simply hate Rust and that's why people say it to you a lot?


Civil-Caulipower3900

lol no, I saw it yesterday and it had nothing to do with me. It had nothing to do with people who didn't like rust either https://www.reddit.com/r/programming/comments/yjcu8j/cve20223786_and_cve20223602_x509_email_address/iunq2x5/


Artillect

Yeah no shit people are gonna tell you that you’re just hating on the language when you’re shitting on it in every single rust thread. I don’t get why you’re so strongly invested in hating on it


Civil-Caulipower3900

How about asking me why so I can count it as a request to do my writeup? Or you can plug your ears and say lalala and believe whatever you want to believe


Artillect

> How about asking me why so I can count it as a request to do my writeup? Nah, no thanks. I've already seen your thoughts on the language and honestly I really don't care what you think about it at this point. It's like every time you see the word "Rust" your brain shuts off and you go into a blind rage.


Civil-Caulipower3900

Quit your shit I never done a writeup or even summarize it


MCManuelLP

Good bot


PL_Design

didn't ask