this post was submitted on 05 Jul 2025
297 points (98.4% liked)

Programmer Humor

25139 readers
1784 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 2 years ago
MODERATORS
top 45 comments
sorted by: hot top controversial new old
[–] dejected_warp_core@lemmy.world 1 points 6 days ago* (last edited 6 days ago)

This was my experience too, until I learned a few things.

  • If you're coming from another programming language, the equivalent capabilities you're probably used to are Box, dyn, and Rc.
  • Dynamic dispatch (dyn) isn't really necessary a lot of the time. Identify where you absolutely need it and solve everything else through other means.
  • You wind up with lifetime specifier problems if you try to do a lot with references (&). Instead, try to re-think your structs and functions using composition and clone/copy instead. It's less efficient, but it's easier to optimize a running program, too.
  • Rust enum, match, if let, and ? are weird, but are where you get the most leverage in the language. Try to master them.
  • derive[...] is a first-class feature with a lot of standard lib support. Always use this to make your custom types mesh with the standard lib more seamlessly.
  • If you are experienced with the "Design Patterns" book, you absolutely need this: https://rust-unofficial.github.io/patterns/intro.html
  • Macros are an advanced feature, but help get you around limitations in generics and the type system in general. it really is worth knowing, and like the preprocessor in C/C++, isn't avoidable at the intermediate level.
  • The compiler digs deep into your code to figure out types where they're not explicitly declared. I've seen it reach into the return type, call-spec, and function calls within that function, to figure out types for things. This is very hard to observe without an IDE that's checking syntax on the fly. Lean into both of those for more readable and maintainable code.
  • if and match are expressions, not statements! You can use either block to evaluate to a single value, useful in composite expressions like let. Example; let x=if y>20 { y } else { 0 }; Or use them to return values from functions (w/o need of a return statement).
[–] kubica@fedia.io 73 points 2 weeks ago (4 children)

The weird part of rust is replacing straight forward semicolons from other languages with the more verbose .unwrap();.

Just kidding, don't lecture me about it.

[–] sbv@sh.itjust.works 47 points 2 weeks ago (2 children)
[–] sukhmel@programming.dev 7 points 2 weeks ago

But then someone will have to deal with it somewhere, better just unwrap it under the carpet.

[–] marcos@lemmy.world 25 points 2 weeks ago (3 children)

The amount of people on the internet seriously complaining that both Rust error handling sucks and that .unwrap(); is too verbose is just staggering.

I will say this: for me, learning rust was 80% un-learning habits from other languages.

People tend to not like it when they have to change habits, especially if those took a long (and painful) time to acquire.

In this particular case, this is the same complaint Go faced with its form of explicit error handling. And Java, for that matter.

Honestly, Rust does a killer job of avoiding checked exceptions and verbose error hooks by way of the ? operator, and requiring all possible match branches to be accounted for. If you embrace errors fully, by using Result<> and custom Error types, your program gets a massive boost in robustness for not a lot of fuss. I recently learned that it gets even better if you embrace enum as a way to define error values, and make sure it implements useful traits like From and Display. With that, error handling code gets a lot more succinct, permitting one to more easily sift through different error values after a call (should you need to). All of that capability far exceeds any perception of clunkyness, IMO.

[–] magic_lobster_party@fedia.io 20 points 2 weeks ago

I think the problem is that many introductory examples use unwrap, so many beginner programmers don’t get exposed to alternatives like unwrap_or and the likes.

[–] wise_pancake@lemmy.ca 3 points 2 weeks ago* (last edited 2 weeks ago) (1 children)

I’ll be honest, when I was learning to program in Java I mostly just wrapped errors in an empty try catch to shut them up, with no regard for actually handling them.

I assume most other learners do that too.

[–] marcos@lemmy.world 4 points 2 weeks ago

Java requiring you to write every exception that can happen in your code isn't helpful.

Explicit error types are great, but Java managed to make them on a way where you get almost none of the upside and is so full of downsides that indoctrinated a generation into thinking knowing your errors is bad.

[–] ImplyingImplications@lemmy.ca 7 points 2 weeks ago (1 children)

Me, every time I try searching a Rust question.

That's easy. Just do:

fn is_second_num_positive() -> bool {
    let input = "123,-45";
    let is_positive =
        input.split(',')
        .collect::<Vec<&str>>()
        .last()
        .unwrap()
        .parse::<i32>()
        .unwrap()
        .is_positive();
    is_positive
}
[–] shape_warrior_t@programming.dev 13 points 2 weeks ago (1 children)

Can't resist pointing out how you should actually write the function in a "real" scenario (but still not handling errors properly), in case anyone wants to know.

If the list is guaranteed to have exactly two elements:

fn is_second_num_positive_exact(input: &str) -> bool {
    let (_, n) = input.split_once(',').unwrap();
    n.parse::<i32>().unwrap() > 0
}

If you want to test the last element:

fn is_last_num_positive(input: &str) -> bool {
    let n = input.split(',').next_back().unwrap();
    n.parse::<i32>().unwrap() > 0
}

If you want to test the 2nd (1-indexed) element:

fn is_second_num_positive(input: &str) -> bool {
    let n = input.split(',').nth(1).unwrap();
    n.parse::<i32>().unwrap() > 0
}
[–] beeb@lemmy.zip 6 points 2 weeks ago* (last edited 2 weeks ago)

Even better to use expect with a short message of what the assumption is: "the string should contain a comma" if it ever panics you'll know exactly why.

[–] daniskarma@lemmy.dbzer0.com 1 points 2 weeks ago* (last edited 2 weeks ago)

You can also use a shorter version .clone();

[–] diffusive@lemmy.world 38 points 2 weeks ago (1 children)

Call me a weirdo but the more errors a compilers give me the happier (albeit a bit frustrated) I am. That stuff generally surfaces in a way or another… and I prefer at compile time 🙂

That said I haven’t spent quality time with Rust yet… so not sure if there are a lot of nitpicks (ala go) or these are valgrind-level of “holy s*** I am so grateful to this tool” 😃

[–] itslilith@lemmy.blahaj.zone 5 points 2 weeks ago (1 children)

The borrow checker makes things a bit more complicated to get running, definitely takes some getting used to when you come from a non-memory safe language. But the compiler is really helpful throughout almost all mistakes, often directly providing an explanation and a suggested fix. One of my favorites programming experiences so far

[–] qaz@lemmy.world 7 points 2 weeks ago* (last edited 2 weeks ago) (1 children)

...definitely takes some getting used to when you come from a non-memory safe language...

I actually think it's more like the opposite. The compiler takes the normal rules you apply to avoid issues with a non-memory safe language like C/C++ and enforces them explicitly where memory safe languages don't have those rules at all. I think lifetimes are much more confusing if you've never dealt with a user after free and usually let GC deal with it.

Also yes the compiler warnings and errors are amazing, the difference between rustc and gcc is night and day.

[–] Lightfire228@pawb.social 3 points 2 weeks ago* (last edited 2 weeks ago)

I can confirm, I've never used a non memory managed language, and the Rust borrow checker is a massive kick in the teeth

But, the more i consider it from the perspective of memory, and pointers, the borrow checker makes a lot of sense

Especially when storing references inside structs, and how mutability affects references

I actually figured out i could fix a re-mutable borrow error by performing the two mutable operations in separate for loops

[–] MadMadBunny@lemmy.ca 33 points 2 weeks ago (1 children)

Learning C, that smasher would never have stopped.

[–] bhamlin@lemmy.world 27 points 2 weeks ago (1 children)

It would also be emitting significantly less helpful messages.

[–] MadMadBunny@lemmy.ca 21 points 2 weeks ago* (last edited 2 weeks ago) (1 children)
[–] CookieOfFortune@lemmy.world 8 points 2 weeks ago

Segmentation fault?

[–] mholiv@lemmy.world 31 points 2 weeks ago (2 children)

Skill Issue.

For reals though adopting a functional style of programming makes rust extremely pleasant . It’s only when people program in object oriented styles that this gets annoying.

No loops, and no state change make rust devs happy devs.

[–] magic_lobster_party@fedia.io 16 points 2 weeks ago (1 children)

I’m a OOP programmer.

I wrap everything within Arc<Mutex<>>.

I’m a happy dev.

[–] mholiv@lemmy.world 11 points 2 weeks ago* (last edited 2 weeks ago) (1 children)

I mean yah. That’s what it takes. But like when I try to write code around Arc<_> the performance just tanks in highly concurrent work. Maybe it’s an OOP rust skill issue on my end. Lol.

Avoiding this leads, for me at least, to happiness and fearless, performant, concurrent work.

I’m not a huge fan of go-lang but I think they got it right with the don’t communicate by sharing memory thing.

[–] PlexSheep 1 points 2 weeks ago (2 children)

You mean mutex? Arc allows synchronous read only access by multiple threads, so it's not a performance bottleneck. Locking a mutex would be one.

[–] tatterdemalion@programming.dev 5 points 2 weeks ago (1 children)

Arc is not free, and the extra atomic operations + heap allocations can become a bottleneck.

[–] PlexSheep 1 points 2 weeks ago (1 children)

Oh, I did not know that. Well, it makes sense that it has a heap allocation, as it becomes more or less global. Though not sure why the atomic operations are needed when the value inside is immutable.

[–] Miaou@jlai.lu 1 points 2 weeks ago

How can you otherwise keep track of an object's lifetime if copies are made concurrently?

[–] mholiv@lemmy.world 3 points 2 weeks ago* (last edited 2 weeks ago)

I mean it could be Mutex, or Rwlock or anything atomic. It’s just when I have to put stuff into an Arc<> to pass around I know trouble is coming.

[–] AnarchoEngineer@lemmy.dbzer0.com 4 points 2 weeks ago (3 children)

I just started learning rust like two days ago and I haven’t had too many issues with OOP so far… is it going to get considerably worse as the complexity of my projects increases?

[–] qaz@lemmy.world 5 points 2 weeks ago

It will become more complex when you start needing circular references in your datastructures.

[–] mholiv@lemmy.world 3 points 2 weeks ago

You’ll be fine. You will learn the lifetime stuff and all will work out. It’s not that bad to be honest.

[–] felsiq@lemmy.zip 1 points 2 weeks ago

Worse in the sense of more errors, sure, but as you go you’ll pick up more of the rust patterns of thinking and imo it’s very worth it. It’s an odd blend and can be a bit verbose but I definitely prefer it to a pure OO or pure functional style language personally

[–] ExLisper@lemmy.curiana.net 19 points 2 weeks ago* (last edited 2 weeks ago)

In my experience rust compiler simply moves the errors to earlier stage of development. With rust I write something and get bunch of errors right in the IDE. I spend some time fixing those and when all the compilation errors are gone in 99% of cases the code works and does what it's supposed to do.

With other languages I write some code and the compiler/interpreter says it's all good. I then run it, get bunch of errors and have to do some debugging, move back and forth between the editor and the command line/browser/application and fix all the bugs one by one.

So yeah, rust compiler complains a lot but it's to make your life easier, not harder. For me working rust way is just much more pleasant. I get immediate visual clues about the errors right in the IDE. When I finally get it right and all the errors dispersal it's like solving a small puzzle. You know you got it and it feels good. With other languages you think you got it all the time only to find another bug when you run it. Doing it this way is much more frustrating.

[–] kamikazerusher@lemmy.world 17 points 2 weeks ago (1 children)

This is my experience every time I return to learning rust. I’m guessing that if I used it more often than once a quarter with hobby projects I’d stop falling into the same traps.

[–] boonhet@sopuli.xyz 9 points 2 weeks ago (1 children)

I find that the error messages themselves are a great tool for learning when it comes to Rust.

[–] kamikazerusher@lemmy.world 4 points 2 weeks ago (1 children)

Eh, I’m not entirely sold on that idea.

I think they do a good job of pointing out “this is a behavior/feature of Rust you need to understand.” However they can send you down the wrong path of correction.

The compiler error mentioning static lifetime specifiers of &str demonstrates both. It indicates to the developer that ownership and scopes will play a significant role when defining and accessing data. The error though will guide them towards researching how to define static lifetimes and possibly believe that they will need to set this in their functions and structs. Each time you look at questions about this error in places like Stack Overflow with example code you’ll find suggested solutions explaining that a manually-defined static lifetime isn’t necessary to resolve the problem.

[–] magic_lobster_party@fedia.io 2 points 2 weeks ago

Static lifetimes confused me when I started learning rust. The error message guides the developer to the wrong direction.

It took me a while to realize that just using Arc is sufficient in most of those cases.

[–] LovableSidekick@lemmy.world 15 points 2 weeks ago* (last edited 2 weeks ago) (2 children)

The old school method of learning a programming language, database, framework or whatever was to read books and take classes, do a series of exercises that teach you how to use the features, and the errors you get if you don't do it right. Then you write code that way for like 10-15 years.

The Information Age method is to find some sample code, copypaste into an editor and hit Compile, then paste compile errors into google and fix them until there are no more. Then hit Run and copypaste/fix runtime errors until there are no more runtime errors. Old-schoolers used to call this hacking, but now it's called not having time to deeply learn the hot new thing because before you do you'll have to start over with the next hot new thing.

Books, classes, and documentation can also be lacking for new tech.

[–] savedbythezsh@sh.itjust.works 2 points 1 week ago

The last language I learned was Rust, I did a mix of the two. I read through the canonical Rust book and then got to coding because I learn more deeply when I can apply what I've learned. It's still a tricky language to keep a conceptual model of in your head though.

[–] tiredofsametab@fedia.io 6 points 2 weeks ago

A friend told me about rust around 8 years ago and this was very much my first experience (at least with &str and lifetimes and borrow errors).

[–] pewpew@feddit.it 3 points 2 weeks ago

C is the way.3̶̧̧̳̉ẻ̵͙̗͍͒h̶͈̗̊͘o̷̡̳̥̒͐̇f̷͍̳͕̐{̸͇̀̒?̷̤͇̀̊p̴̰̆̍̕