Hacker News new | ask | show | jobs
by boxmonster 2000 days ago
I recently wrote a utility for myself in Rust after having done several in C#. I like both languages, but Rust introduces pain points for no apparent reason. For example, I hate this way of dealing with errors

    match result {
        Ok(value) => value,
        Err(result) => { 
            panic!("error traversing directories {}", result);
        }
    };
It's awkward and ugly. I'm back to C#, now on .NET 5.) and find that it just got noticeably faster! It was already fast.

"Astonishing Performance of .NET 5: More Data"

https://medium.com/swlh/astonishing-performance-of-net-5-mor...

4 comments

This code is equivalent to

    result.unwrap_or_else(|e| panic!("error traversing directories {}", e));
There are a lot of methods on various types to reduce this kind of thing. If you didn't want to interpolate the value of e, it would be even simpler:

    result.expect("error traversing directories");
> If you didn't want to interpolate the value of e

For those reading along (not Steve) expect does do that, but using the Debug formatter instead of Display, as the grandparent used.

the unwrap_or_else makes a lot more sense, because I could just use the ? operator, but if I don't want to panic, then I'll use unwrap_or_else. I am not by any means an advanced Rust programmer and in fact learning from your book, so I didn't mean to offend anyone. My initial impression of the match syntax for return values was that I didn't like it. Sorry.
Match has it's place in unpacking common Enum types like Option and Result, but typically you'll reach for functional patterns like `Result::map`, `Result::expect`, `Result::unwrap_or`, and of course `?` as they're able to do the same thing but in far less code.

I think the downvotes are because both the example and the generalized statement that C# is "noticeably faster" is bait / lazy.

The railway error-handling paradigm is superior (in my mind) to the common try/catch/throw pattern in many other languages. It promotes errors to first class citizens. It's a monadic pattern that many functional programmers like to employ.
Definitely not bait because I like to jump around with languages so it's natural for me to compare them (that's why I do it.) I wrote my web server in Go, my util to find duplicate directories in Rust, etc.. I wasn't saying C# is faster than Rust, I said C# got faster.
> I wasn't saying C# is faster than Rust, I said C# got faster.

Ah gotcha - my mistake :)

It's all good!
"I recently wrote a utility for myself in ASM after having done several in C. I like both languages, but ASM introduces pain points for no apparent reason."

IMO the_duke summarized it perfectly in other comment: You are essentially complaining that Rust is not C#; Rust is much lower level and makes very different tradeoffs; most of the design decisions are there for a reason, and are good choices (https://news.ycombinator.com/item?id=25593825)

People considering Rust as an alternative for higher-level programming languages are in for a potential surprise or two. I guess this happens because Rust has received a lot of attention and promotion, enough to make some people consider it, where otherwise they wouldn't have thought of using tools that stand at a lower level than what is most appropriate for their needs (or knowledge).

EDIT: I've now read that in this particular case, the parent commenter is consciously playing with different languages to learn about them. Still, I think it would be a misconception to think that C# and Rust are at an equivalent level of programming abstraction, and thus should offer similar ergonomics.

It's funny. Rust is a strange beast. It's a low level language. But, in some specific ways, it's more expressive than a lot of popular high level languages: traits are sometimes nicer than interfaces, strong concurrency guarantees are great compared to the nightmare of parallel processing in e.g., Java, discriminated unions with pretty good pattern matching is missing from many popular high level languages.

You still have languages that can't (really) even do async/threaded computation (Python, PHP, JavaScript/Node can't do threads AFAIK).

I've said this before: "Rust is the highest level low level language I've ever used. Java is the lowest level high level language I've ever used."

HN won't let me edit my comment to clarify (after 2 hours?) but I was pleasantly surprised that Rust felt like C# to me and I didn't have to struggle much because I already know about references, pointers, stacks and heaps (from C and asm) Dictionaries and Lists were easy to work with. I grokked the borrow checker. I was motivated to make my post because I struggle with the various return types and syntax like

    enum Result<T, E> {
       Ok(T),
       Err(E),
    }

    match header.get(0) {
        None => Err("invalid header length"),
        Some(&1) => Ok(Version::Version1),
        Some(&2) => Ok(Version::Version2),
        Some(_) => Err("invalid version"),
    }
I wasn't saying it was bad, just a pain point for me.
Now try learning about Go's error handling, you will feel better about it :) /s

Jokes aside there are many helper methods on `Result` to make it more Rustic, try looking into: https://doc.rust-lang.org/std/result/enum.Result.html

This is pretty nonsensical code so kind of hard to see what your point is.
If the value were being assigned to a variable, it would make tons of sense, IMHO. That it's not means that it's a little useless, but I'm guessing this was typed up for this example, not copy/pasted from real code.