←back to thread

177 points signa11 | 10 comments | | HN request time: 1.448s | source | bottom
Show context
Aurornis ◴[] No.42161106[source]
A theme I’m noticing more frequently as Rust gains popularity is people trying to use Rust even though it doesn’t fit their preferred way of coding.

There is a learning curve for everyone when they pick up a new language: You have to learn how to structure your code in ways that work with the language, not in the ways you learned from previous languages. Some transitions are easier than others.

There should come a point where the new language clicks and you don’t feel like you’re always running into unexpected issues (like the author of this article is). I might have empathized more with this article in my first months with Rust, but it didn’t resonate much with me now. If you’re still relying on writing code and waiting for the borrow checker to identify problems every time, you’re not yet at the point where everything clicks.

The tougher conversation is that for some people, some languages may never fully agree with their preferred style of writing code. Rust is especially unforgiving for people who have a style that relies on writing something and seeing if it complies, rather than integrating a mental model of the language so you can work with it instead of against it.

In this case, if someone reaches a point where they’re so frustrated that they have to remember the basic rules of the language, why even force yourself to use that language? There are numerous other languages that have lower mental overhead, garbage collection, relaxed type rules, and so on in ways that match different personalities better. Forcing yourself to use a language you hate isn’t a good way to be productive.

replies(4): >>42161149 #>>42161234 #>>42162570 #>>42164055 #
1. dwattttt ◴[] No.42161149[source]
> A theme I’m noticing more frequently as Rust gains popularity is people trying to use Rust even though it doesn’t fit their preferred way of coding.

I could've expressed the sentiment in this blog post back when I started playing with Rust ~2016. Instead, I ended up learning why I couldn't pass a mutable reference to a hashmap to a function I'd looked up via that hashmap (iterator invalidation lesson incoming!).

The kind of bug I was trying to add exists in many languages. We can only speak in general terms about the code the blog post is talking about, since we don't have it, but couching it in terms of "doesn’t fit their preferred way of coding" misses that the "preferred way of coding" for many people (me included) involved bugs I didn't even realise could exist.

replies(3): >>42161208 #>>42161209 #>>42162462 #
2. Const-me ◴[] No.42161208[source]
> The kind of bug I was trying to add exists in many languages

Any example except C++? BTW, the closest thing possible in C# is modifying a collection from inside foreach loop which iterates over the collection. However, standard library collections throw “the collection was modified” exception when trying to continue enumerating after the change, i.e. easy to discover and fix.

replies(3): >>42161262 #>>42161962 #>>42162160 #
3. AlienRobot ◴[] No.42161209[source]
I'm pretty sure most languages just make the reasonable assumption that you want to map to the object so it uses the pointer for hashing and not actually hash its value.
replies(1): >>42161275 #
4. dwattttt ◴[] No.42161262[source]
> modifying a collection from inside foreach loop

This is exactly what the mutable map pointer was for, for the function to be able to modify the collection; C++ would result in potentially iterating garbage, C# it sounds like would throw an exception (and so show the design wouldn't work when I tried to test it), Python definitely didn't do a graceful thing when I tried it just now. And if I had a collection struct in C, I'm sure I could've done some horrible things with it when trying.

The best of those outcomes is C#, which would've shown me my design was bad when I ran it; that could be as early as the code was written if tests are written at every step. But it could be quite a bit later, after several other interacting parts get written, and you rely on what turns out to be an invalid assumption. For Rust, the compiler alerted me to the problem the moment I added the code.

FTR I ended up accumulating changes to the map during the loop, and only applying them after the loop had finished.

EDIT: Python did do something sensible: I didn't expect pop'ing an element from the list to echo the element popped in the REPL, and got a printed interleaved from front to back, which does makes sense.

replies(1): >>42162386 #
5. ◴[] No.42161275[source]
6. cyberax ◴[] No.42161962[source]
> Any example except C++?

Java for sure.

> However, standard library collections throw “the collection was modified”

Java is similar, but the exception is done on a "best effort" basis, and is not guaranteed.

7. nurettin ◴[] No.42162160[source]
Python will raise a runtime exception if you modify the dict you are iterating over. You can work around that by copying a snapshot of the whole thing or just the keys and iterating over that.

C++ will laugh in invalidated iterators.

Of course you can erase from the container you are iterating over, but you have to make sure to continue the iteration using the iterator returned from the erase function and avoid storing copies of .end()

8. dgoldstein0 ◴[] No.42162386{3}[source]
Python defined the semantics of modifying lists while iterating over them, which is better than c/c++ just calling it undefined behavior, but I've basically never seen it not be a bug. Either I end up creating a copy of the list to iterate over, or figure out a way to defer the modifications, or write a new list. Imo the c# /Java behavior of detecting and throwing is probably the best option for non borrow checked languages.
9. o11c ◴[] No.42162462[source]
And yet, such mutation is perfectly safe as long as you only change the value of existing keys. But you can't do that in Rust.
replies(1): >>42162514 #
10. dwattttt ◴[] No.42162514[source]
You would use interior mutability, putting things in Cells in the map.