crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.49k stars 1.62k forks source link

Refactor `Enumerable#map` to delegate to `#map_with_index` #15210

Closed straight-shoota closed 11 hours ago

straight-shoota commented 2 days ago

#map and map_with_index are identical except that the latter also yields an index counter.

But this counter is entirely optional and can be omitted from the block. It's possible to call #map_with_index with exactly the same signature as #map.

["foo", "bar"].map_with_index do |e|
  e.upcase
end # => ["FOO", "BAR"]

["foo", "bar"].map do |e|
  e.upcase
end # => ["FOO", "BAR"]

The implementation of both methods is also pretty much identical, in Enumerable as well as in any including type. Of course, map_with_index has a counter and yields its value. But LLVM optimization happily removes it when unused.

So I think it makes sense to implement Enumerable#map by delegating to #map_with_index. This embodies the close connection between these two methods. As a result, including types only need to override #map_with_index with a custom implementation and #map will follow suit. Including types may still override #map with a custom implementation, of course.