Most active commenters
  • kstrauser(3)
  • kanbankaren(3)

←back to thread

177 points signa11 | 28 comments | | HN request time: 0.812s | source | bottom
1. kstrauser ◴[] No.42160831[source]
Rust was a pain in the ass until I stopped trying to write C code in it and started writing idiomatic Rust. I don’t know the author of this blog, but he mentions extensive C++ experience which makes me wonder if he’s trying to write C++ in Rust.

Maybe not! Maybe it’s truly just Rust being stubborn and difficult. However, it’s such an easy trap to fall into that I’ve gotta think it’s at least possible.

replies(3): >>42160844 #>>42161027 #>>42161181 #
2. maguirre ◴[] No.42160844[source]
Are there examples one can learn from about idiomatic rust? I would appreciate either books or projects to learn from.
replies(3): >>42160890 #>>42160891 #>>42161001 #
3. kstrauser ◴[] No.42160890[source]
https://doc.rust-lang.org/book/ is great. I’d been writing Rust for months before I started reading it and still began learning new things from the start. Oh, that’s why it does this!

Edit: Oh! And use “cargo clippy” regularly. It makes excellent recommendations for how to make your code more idiomatic, with links to docs explaining why it’s nicer that way.

4. galangalalgol ◴[] No.42160891[source]
Rust, like ocaml, is best when used purely functionally until you run into something that isn't performant unless its imperative. But unlike ocaml or haskell there is a safe imperative middle ground before going all the way to unsafe. People who write modern C++ with value semantics etc. seem to have a lot less trouble than people coming from Java.
replies(3): >>42161004 #>>42161039 #>>42165146 #
5. zeta0134 ◴[] No.42161001[source]
Generally I have the easiest time when I declare my state in the outermost scope possible, and then pass it into functions that need to operate on it. If I'm using an actual pointer, rather than a mutable reference that came in as an argument, something weird is happening! Usually that's the interface with some external library.

Rust in particular is *really* obnoxiously bad at OOP patterns, and I think my lesson at this point is that this is because it is hard to do OOP safely, at least in a way that jives with its borrow checker. Something like functional core, imperative shell seems to be a much nicer flow for the thing in general.

Anyway, I've just got the one major Rust project (an NES emulator) so I'd say I'm pretty early in my Rust journey. For me personally, the good points (delightful match, powerful enum) outweigh the bad (occasional borrow checker weirdness, frustrating lifetimes) but I think it depends a lot on what you're trying to do with it.

replies(1): >>42161062 #
6. lowbloodsugar ◴[] No.42161004{3}[source]
I mean, I don’t write it that way, but if it works for you. I wouldn’t say you have to write it that way so I wouldn’t want to put anyone off.

Thinking about your answer a bit more, one of the paradigms of Rust is “there shall be many immutable references or just one mutable reference” and so I can see that functional programming would naturally lead to that. But it’s a paradigm that works with the underlying principles rather than the true nature of the language, IMHO.

I do it by thinking about different domains of object graphs, and how data moves between them, for example.

7. nicce ◴[] No.42161027[source]
I learned Rust before learning C properly.

Oh boy. I see bugs everywhere in C and why the borrow checker exists. It really forces you to understand what happens under the hood.

The most issues in Rust are indeed related the expressions - you don't know how to describe some scenario for compiler well-enough, in order to prove that this is actually possible - and then your program won't compile.

In C, you talk more to the computer with the language syntax, whereas in Rust you talk to the compiler.

replies(3): >>42161173 #>>42161240 #>>42162370 #
8. nh2 ◴[] No.42161039{3}[source]
It's difficult to really use Rust purely functionally given that it removed pure functions from its type system, and that has a limited stack size.
9. ijustlovemath ◴[] No.42161062{3}[source]
You can achieve some level of OO design by using traits (the generic kind, not the dyn kind), but I think the functional style and inline testing gives you a ton of nice properties for free!

Rust also pushes you to refactor in a way that really pulls out the core of your problem; the refactoring is just you understanding the problem at a deeper level (in my experience)

10. kanbankaren ◴[] No.42161173[source]
> Oh boy. I see bugs everywhere in C and why the borrow checker exists.

Any examples that you could provide? I have been dealing with C/C++ for close to 30 years. Number of times I have shot myself with undefined/unspecified behavior is less than 5.

replies(5): >>42161886 #>>42162308 #>>42162360 #>>42162444 #>>42164671 #
11. Aurornis ◴[] No.42161181[source]
> Rust was a pain in the ass until I stopped trying to write C code in it and started writing idiomatic Rust.

This is the #1 problem I see with people trying to learn a new language (not just Rust).

I’ve watched enough people try to adopt different languages at companies over the years that I now lean pessimistic by default about people adopting new languages. Many times it’s not that they can’t learn the new language, it’s that they really like doing things the way they learned in another language and they don’t want to give up those patterns.

Some people like working in a certain language and there’s nothing wrong with that. The problems come when they try to learn a new language without giving up the old ways.

Like you, I’m getting similar vibes from the article. The author wants to write Rust, but the entire premise of the article is about not wanting to learn the rules of Rust.

replies(5): >>42161933 #>>42162613 #>>42163170 #>>42167602 #>>42170866 #
12. marcosdumay ◴[] No.42161240[source]
> In C, you talk more to the computer with the language syntax, whereas in Rust you talk to the compiler.

The C compiler pretends to be the computer. But UB is still there, as a compiler-only thing that has no representation at all on the computer.

13. dafelst ◴[] No.42161886{3}[source]
The borrow checker isn't just about UB, it is mostly about memory safety.

I'm sure you've seen plenty of use-after-frees/use-after-move/dangling pointer type things or null pointer derefs, or data races, etc etc. These are largely impossible to do in safe rust.

14. zanderwohl ◴[] No.42161933[source]
> This is the #1 problem I see with people trying to learn a new language (not just Rust).

Definitely! I've also noticed people will learn a group of similar languages, like Java, C#/.Net, then Kotlin as the most distant relation. Now, they think they know many languages, but they mainly have the same core idea. So when they try something new like Haskell or Swift or Rust, they think it's doing something different from the "norm" in a really irritating way.

15. jjnoakes ◴[] No.42162308{3}[source]
The number of times you shot yourself in the foot that you know about. Some of those bullets just haven't landed yet. C and C++ give you very interesting foot-guns: sometimes they go off even when you don't touch them (compiler upgrade, dependencies changing, building on a new architecture, ...)
16. tsimionescu ◴[] No.42162360{3}[source]
In 30+ years of experience in C, you haven't used a free()d variable or written past the end of a buffer more than 5 times? If that's true, then you have more care and attention than 99.99% of all C experts.
replies(1): >>42164732 #
17. dbtc ◴[] No.42162370[source]
> In C, you talk more to the computer with the language syntax, whereas in Rust you talk to the compiler.

C is like a fast motorcycle, rust is a car with driver-assistance system.

18. oneshtein ◴[] No.42162444{3}[source]
Borrow checker checks memory safety. Undefined/unspecified behavior still present in Rust[1].

[1]: https://doc.rust-lang.org/reference/behavior-considered-unde...

replies(1): >>42162632 #
19. donatj ◴[] No.42162613[source]
Trying to convince developers from "classical" OO that not everything needs to be a class in JavaScript has been a major thorn in my side for years. Your little procedure with no state? That can just be an exported function.
20. bombela ◴[] No.42162632{4}[source]
Only from code annotated unsafe. In other words, if you do not use the keyword unsafe, you have no undefined behaviors.
21. pansa2 ◴[] No.42163170[source]
> The problems come when they try to learn a new language without giving up the old ways

In Python, I frequently see the same problem from the other side. Instead of C/C++ programmers learning Rust and "not wanting to learn the rules of Rust", it's Java/C# programmers learning Python and not wanting to unlearn the rules of Java/C#. They write three times as much code as they need to - introducing full class hierarchies where a few duck-typed functions would do.

22. eddd-ddde ◴[] No.42164671{3}[source]
Clearly you must be superhuman then, something as simple as forgetting a null pointer check is bound to hit you every now and then.
replies(1): >>42164757 #
23. kanbankaren ◴[] No.42164732{4}[source]
I should have been clear.

Of course, I have done such mistakes, but they were caught early in the dev. process. I am talking about bugs that were caught in production due to misunderstanding of C compilers on 16/32 bit processors.

I also avoid idioms like *p instead write p[i] whereever possible.

24. kanbankaren ◴[] No.42164757{4}[source]
Of course, I do, but they are caught early in the dev. process. Not in production though.
replies(1): >>42165006 #
25. kstrauser ◴[] No.42165006{5}[source]
I would contend that’s an unusually sophisticated dev process not used by most.
26. IshKebab ◴[] No.42165146{3}[source]
Most Rust code is not purely functional in my experience. It's quite similar in style to C++ except:

1. No class hierarchies and inheritance.

2. The borrow checker forces a tree structured ownership style. You don't get spaghetti ownership. This is generally great because that coding style leads to fewer bugs. But sometimes it is annoying and you have to use indices rather than pointers as references.

27. dijksterhuis ◴[] No.42167602[source]
it’s not just languages.

i had similar problem with tensorflow for like a year or so until it “clicked” i was trying to make the framework do thing the way i wanted, instead of doing things the way the framework wanted.

seeing that in myself was a real eye opener.

now i see it in others too and it’s frustrating because, ultimately, no-one can tell them they’re doing it. they have to find out for themselves for it to make a difference for how they act.

28. munksbeer ◴[] No.42170866[source]
Would you be able to give an example of what you mean? What it would look like trying to write C code in Rust and then the idiomatic Rust way?