hamstergem/hamster — pull request #101 by alexdowad (2014-06-30 19:12:37+00:00)
Title: Make Hamster::Hash match Ruby Hash API (everywhere it makes sense)

This is a backwards-compatibility breaking change, so I expect that there will be some discussion. In short, these patches bring the `Hamster::Hash` API in close line with Ruby's built-in `Hash`. That means:

1. It must yield `[key, value]` arrays rather than `key` and `value` as separate arguments. This is not such a big change, since Ruby *automatically* unpacks single `Array` arguments when they are passed to a block which takes 2 or more arguments. This means that the great majority of existing code which uses Hamster will continue to work.

2. Iterator methods must return an `Enumerator` if they are called with no block.

3. If `#reduce` is called with a `String`/`Symbol` argument and no block, it must use the arg as the name of a method to be used as a reducing function.

4. `#reduce` must work when passed a block and no seed value (the first key/val pair should be used as the seed value). It didn't do this before.

To help add some of the needed methods, I `include`d Ruby's built-in `Enumerable` in `Hamster::Hash`. Yes, Hamster has its own `Enumerable` module, but I feel it is redundant. Most of the methods it defines are identical in behavior to the built-in `Enumerable`. In cases where we want different behavior, we can simply override the needed methods. (For an example, see how I implemented `Hamster::Hash#partition`.)

The built-in `Enumerable` will be faster, and we can rest assured that if future versions of Ruby make adjustments to the behavior of the `Enumerable` methods, `Hamster` will automatically follow the behavior of whichever version of Ruby you run it on.

As an aside, this implementation of `#partition` also overcomes a problem with Hamster's `Enumerable#partition` -- that implementation calls the passed block *twice* for each item. If someone uses a block with side effects, this could be a nasty surprise. This `#partition` just calls the block once for each item.

Closes #31 and #42.