
Issue #19830 has been reported by tomstuart (Tom Stuart). ---------------------------------------- Feature #19830: Allow `Array#transpose` to take an optional size argument https://bugs.ruby-lang.org/issues/19830 * Author: tomstuart (Tom Stuart) * Status: Open * Priority: Normal ---------------------------------------- One benefit of supplying an initial value to `Enumerable#inject` is that it avoids an annoying edge case when the collection is empty: ```
[1, 2, 3].inject(:+) => 6 # good
[].inject(:+) => nil # bad
[].inject(0, :+) => 0 # good
A similar edge case exists for `Array#transpose`:
[[1, :a], [2, :b], [3, :c]].transpose => [[1, 2, 3], [:a, :b, :c]] # good
[].transpose => [] # bad
Although no explicit `nil` is produced here, the subtle problem is that the caller may assume that the result array contains arrays, and that assumption leads to `nil`s in the empty case:
[[1, :a], [2, :b], [3, :c]].transpose.then { _2.join } => "abc"
[].transpose.then { _2.join } undefined method `join' for nil:NilClass (NoMethodError)
If we allow `Array#transpose` to take an optional argument specifying the size of the result array, we can use this to always return an array of the correct size:
[[1, :a], [2, :b], [3, :c]].transpose(2) => [[1, 2, 3], [:a, :b, :c]] # good
[].transpose(2) => [[], []] # good
By avoiding an unexpectedly empty result array, we also avoid unexpected downstream `nil`s:
[[1, :a], [2, :b], [3, :c]].transpose(2).then { _2.join } => "abc"
[].transpose(2).then { _2.join } => ""
Here is a patch which adds an optional argument to `Array#transpose` to support the above usage: https://github.com/ruby/ruby/pull/8167
Something similar was requested eleven years ago in #6852. I believe this feature addresses the problem expressed in that issue without compromising backward compatibility with existing callers of #transpose.
--
https://bugs.ruby-lang.org/