3 ms·
> My pet frustration in Ruby is `.slice` behavior. I would argue that any input that doesn't have exactly one obviously correct output should result in an exce
by jeffparsons 2y ago
> My pet frustration in Ruby is `.slice` behavior.
I would argue that any input that doesn't have exactly one obviously correct output should result in an exception being raised. But Ruby often shies away from doing that. My interpretation is that they prefer to return _something_ rather than blowing up, so the show can go on.
I guess I sit at the opposite end of the philosophical spectrum from Ruby, so it's no wonder choices like this frustrate me. My personal philosophy is "explode early, explode often", because propagating invalid states only leads to future pain and suffering.
> [...] so much code now relies on its behavior, predictably or otherwise, that they couldn't change it.
I'm not denying this is a reason for keeping the questionably behaviour, but it's kind of funny because Ruby also introduces subtly backward-incompatible changes semi-regularly, including in "minor" releases. (Maybe that last bit is unfair, because I don't think that Ruby has ever claimed to follow semver.)
- Terr_ 2y ago> My interpretation is that they prefer to return _something_ rather than blowing up, so the show can go on. I think I saw this horror movie, but it was titled "PHP." :p
- sqeaky 2y agoI agree it isn't entirely obvious at first glance why slice behaves the way it does, there is a pattern. If the first number in the range is a valid index into the string then you'll get something back, and if it isn't you can't get anything back so you have to get back a nil. Coming from a C++ background my time in Ruby was weird and enlightening, it was less specified than C++, but pretty much everything is. I don't think it was underspecified, but a lot of the behavior was meant to be intuited and follows some kind of underlying pattern. If you miss the pattern you miss a lot of the functionality of that part of the language. I agree that failing early and often is generally preferable. I don't see that Ruby doesn't do that, it just has more definitions for generic behaviors. Consider the amount of things in the range from the original post that produce type errors. Last time I checked both the C++ language and the C++ standard Library both had about twice as many pages in The Standard than all of Ruby in its standard Library have, yet there is still undefined and implementation to find behavior. So there are places where we get weird an unexpected Behavior that can result in bad State being passed around even in very formally specified places.
- wavemode 2y ago> If the first number in the range is a valid index into the string then you'll get something back, and if it isn't you can't get anything back so you have to get back a nil But, 3 is not a valid index into a string of 3 characters. By your criteria, "abc"[3] correctly returns nil. Whereas "abc"[3,1] returns "" The language designers really just did not think this through.
- lloeki 2y ago> but Ruby often shies away from doing that. My interpretation is that they prefer to return _something_ rather than blowing up, so the show can go on. There are two (intertwined) explanations: - In Ruby exceptions are costly to generate. - Similar to Go, Ruby's stdlib design favours using return values for signalling, keeping exceptions for exceptional cases. So in plain† Ruby there are a lot of places that use `nil` to signal that something's off, e.g `[1,2,3][4]` returns `nil` because it's an out of bounds access, or `"123".downcase!` returns `nil` because nothing has been downcased, or `__FILE__` returns `nil` when a file is `eval`'d. So yes, you have to check for things like `nil` (or explicitly swallow with `&.` which is kind of a Maybe monad pattern) before doing stuff with values, just like you check for `if err == nil` in Go. Running a type checker like `steep` helps a lot linting for these cases. † Rails likes to generate exceptions, but Rails != the whole of Ruby.