# Ruby 2.7 new Enumerable methods

**URL:** <https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800>\
**Category:** Crystal Contrib\
**Created:** [May 28, 2019, 1:58pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800 "2019-05-28T13:58:16Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [May 28, 2019, 1:58pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/1 "2019-05-28T13:58:16Z")

</div>

Ruby 2.7 adds a couple of new methods to `Enumerable`:

- `Enumerable#filter_map`. For example: `(1..10).filter_map { |i| i * 2 if i.even? } # => [4, 8, 12, 16, 20]`. This is useful to avoid having to do `.select { ... }.map { ... }` which creates an intermediate array and it’s a very common idiom in functional languages (like Haskell and Elm).
- `Enumerable#tally`. For example `['a', 'b', 'a', 'b', 'b'].tally # => {'a' => 2, 'b' => 3}`. Counting things is pretty common, I think.

Should we add these to Crystal? They seem easy to implement and generally useful.

---

<div class="post-metadata">

**Author:** ![bew](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bew/32/113_2.png) [@bew](https://forum.crystal-lang.org/u/bew)\
**Post date:** [May 28, 2019, 2:44pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/2 "2019-05-28T14:44:40Z")

</div>

For `Enumerable#filter_map` we already have `Enumerable#compact_map` which does just that!

---

<div class="post-metadata">

**Author:** ![konovod](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/konovod/32/229_2.png) [@konovod](https://forum.crystal-lang.org/u/konovod)\
**Post date:** [May 28, 2019, 10:03pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/3 "2019-05-28T22:03:12Z")

</div>

`tally` is nice, i’ve even used such function few times.  
But I have to say that (as non-native speaker) never heard this word so would never guess this name. Maybe it’s just me.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [May 28, 2019, 11:39pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/4 "2019-05-28T23:39:29Z")

</div>

> [@konovod](#):
>
> But I have to say that (as non-native speaker) never heard this word so would never guess this name.

I agree. The same happened to me too. I think Ruby chose that name because chances of it colliding with a user-defined method named like that is very unlikely.

---

<div class="post-metadata">

**Author:** ![drosehn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/drosehn/32/72_2.png) [@drosehn](https://forum.crystal-lang.org/u/drosehn)\
**Post date:** [May 29, 2019, 9:49pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/5 "2019-05-29T21:49:45Z")

</div>

`tally` seems like a fine name to me, as an american (although I suspect it’s more widely used in England than the USA). As soon as I saw the method name, I knew what it was going to do.

On the other hand, it does seem to be true that I’ve never thought to use it in any program I’ve written, even though I have quite a few programs which have tallied things up like that!

---

<div class="post-metadata">

**Author:** ![drosehn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/drosehn/32/72_2.png) [@drosehn](https://forum.crystal-lang.org/u/drosehn)\
**Post date:** [May 29, 2019, 9:53pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/6 "2019-05-29T21:53:49Z")

</div>

For me at least, I think the name of `filter_map` is somewhat better than `compact_map`. And it’s one character shorter! 🙂

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/rogerdpack/32/117_2.png) [@rogerdpack](https://forum.crystal-lang.org/u/rogerdpack)\
**Post date:** [October 2, 2019, 5:32pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/7 "2019-10-02T17:32:58Z")

</div>

Speaking of which, twould be nice to have the “lazy eval” type chaining so that no intermediate arrays are required [wait does that actually speed up things though? LOL]. And, following on after that, the java style “parallel stream” chains. Do those speed things up? Also don’t know…

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [October 31, 2024, 6:05pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/8 "2024-10-31T18:05:42Z")

</div>

Why we add tally, but not add filter\_map? filter\_map is it totally different with `compact_map` .

`filter_map` same as `select {....}.map {...}`  
`compact_map`, is same as `map {...}.compact`

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [October 31, 2024, 6:23pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/9 "2024-10-31T18:23:24Z")

</div>

Technically you can use `compact_map` to do what `filter_map` does by just doing like `next unless condition`. The `nil` values will be filtered out so you end up with a filtered array from only a single iteration of the source collection.

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [October 31, 2024, 6:43pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/10 "2024-10-31T18:43:39Z")

</div>

Use Ruby or Crystal, prefer write clean code, filter\_map is more clear than compact\_map when do same thing.

in fact, both of them not same, compact\_map only can do part of filter\_map thing, we really should add `filter_map` instead of `compact_map` (or both), because the former is the superset of latter.

```auto
# Crystal
ic(1.14.0):005> [1, 2, 3, nil].compact_map { |i| i == nil }
 => [false, false, false, true]

# Ruby
[2] pry(main)> [1, 2, 3, nil].filter_map { |i| i == nil }
=> [true]

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [October 31, 2024, 6:54pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/11 "2024-10-31T18:54:55Z")

</div>

```crystal
icr:5> [1, 2, 3, nil].compact_map { |i| i.nil? ? true : nil }
 => [true]

```

Not saying we shouldn’t add it, just that `compact_map` can work as a more efficient version of `.select { }.map { }` until if/when `filter_map` is a thing. This is really the first we’re hearing of a use case for it, so must not have been all that desired until now.

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [November 1, 2024, 4:11pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/12 "2024-11-01T16:11:09Z")

</div>

okay, we should not guide users to use `compact_map` instead of `filter_map` anyway, it’s really a BAD part.

---

<div class="post-metadata">

**Author:** ![Sija](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/sija/32/737_2.png) [@Sija](https://forum.crystal-lang.org/u/Sija)\
**Post date:** [November 9, 2024, 4:43pm UTC](https://forum.crystal-lang.org/t/ruby-2-7-new-enumerable-methods/800/13 "2024-11-09T16:43:14Z")

</div>

There’s shorter and more idiomatic version:

```auto
[1, 2, 3, nil].compact_map { |i| true if i }

```
