6 ms·
While on the topic, I still don‘t get it why we have [].last but {}.last fails with a NoMethodError.
by faebi 4y ago
While on the topic, I still don‘t get it why we have [].last but {}.last fails with a NoMethodError.
- saghm 4y agoAre hashes guaranteed to be ordered in some way (not just incidentally implemented that way, but specified so that changing it in the future would be considered breaking)? I thought they weren't, in which case there wouldn't really be any obvious way to define `last`, but I might be mistaken
- danielheath 4y agoRuby hashes are ordered, per the docs.
- sodapopcan 4y ago`{}.first` works, so no reason why `{}.last` shouldn't. I would argue, though, that it's best not to rely on hashes for ordering, though that's a relatively loose preference, and I've certainly use it for quick 'n' dirty scriptss
- latortuga 4y agoRuby hashes have been intentionally ordered since Ruby 1.9, which is ~15 years now.
- sodapopcan 4y agoYep, as I described in another comment I just don't like to exploit that, but it's more of a personal preference. It's cool by me if others choose to.
- BurningFrog 4y agoI agree that it's conceptually weird, but since Ruby guarantees the ordering, you might as well have features for it.
- Lammy 4y agoThe best feature of `Hash` maintaining insertion order is that `Set` does too, since a `Set` is a `Hash` with all-`true` values: https://github.com/ruby/ruby/blob/3539da64fc42d6eb76f1d4c3ccd219c3259ecd8b/lib/set.rb#L522 https://github.com/ruby/ruby/blob/3539da64fc42d6eb76f1d4c3cc...
- sodapopcan 4y agoYa, it's one of things you have to make a team/org-level call on. For me, ruby is full of a lot of little conveniences that shouldn't necessarily be used in production systems. I always cry loud that code should be quickly "scannable", and the data-structures we choose to use can help a lot in the quicker understanding an unfamiliar piece of code. But I stress again: these types of decisions are best left up to the team or org. It's ultimately low-stakes.
- benatkin 4y agokey ordering is something to rely on now, in Ruby as well as in JavaScript and Python That ship has sailed - it was partly for the convenience of debugging, but the general purpose dict is now ordered. It's only by insertion order - it's expensive to change the order - but the order can by relied upon and is being used. Edit: some detail on changing the order - you can either remove all the key/value pairs up to the first one you want to change and add them back, or you can create a new dict with the pairs in the desired order. With Rust you can choose whether or not to have insertion order preserved https://stackoverflow.com/questions/42723065/how-to-sort-hashmap-keys-when-serializing-with-serde https://stackoverflow.com/questions/42723065/how-to-sort-has...
- sodapopcan 4y agoYa, my preference still stands whether the ship is docked or not. As you point out: it's good for debugging. As I mentioned, I like it for quick things in throwaway scripts. I don't like it in production code because when I'm reading something quickly that I don't care to deeply understand: Hashes are records and arrays order ordered lists. I very much like the way Rust does it (and I like a lot of what I've seen in Rust)--if we had `OrderedHash` in Ruby, I will feel completely different.
- Zanius 4y agoMight be some kind of linked list like implementation under the hood. Getting the first element is performant but traversing everything to find the last one would be slow.
- KMag 4y agoThat's very unlikely. Even for singly linked lists, implementations for general purpose use usually keep pointers to the first and last elements so that you can use it as an O(1) FIFO queue, as well as prepend in O(1) time. If you only keep a pointer to the head of the linked list, then it can be practically used a LIFO queue (stack), and a few other corner cases, but not much else. (A FIFO isn't very useful if adding an item is O(1) but removing an item is O(N), or vice versa.)
- Lammy 4y agoSince 1.9: https://bugs.ruby-lang.org/issues/994 https://bugs.ruby-lang.org/issues/994
- the-alchemist 4y agoYeah, that's strange to me too. In Clojure (similar conceptual mode with Ruby, with sequences, hashes, etc.), the code is very similar, with predictable results: Clojure 1.11.1 user=> (first []) nil user=> (first {}) nil user=> (last []) nil user=> (last {}) nil user=>
- e12e 4y agoHash#first comes from Enumerable - and Enumerable doesn't have #last.