eachで回してるときの次の要素がほしい

Route 477(2007-06-12)
あー、これはよくありますねー。Haskellだとひとつずらしてzipっていうのが定石な気がします。一番最後の要素をどうするかっていうのは場合によりけりで悩ましいところですが。

main = print $ f [1, 2, 3, 4, 5]
  where
    f xs = zip xs $ tail xs
-- => [(1,2),(2,3),(3,4),(4,5)]

Rubyの場合ですが、prevやsuccが暗黙的に束縛されるのは名前が衝突しそうで気持ち悪いです。ごく普通に実装するとこんな感じでしょうか。端っこの場合はとりあえずnilにしています。

#!/usr/bin/env ruby

class Array
  def each_with_prevsucc
    each_index do |i|
      prev = (i - 1 < 0) ? nil : self[i - 1]
      item = self[i]
      succ = (i + 1 >= size) ? nil : self[i + 1]
      yield(prev, item, succ)
    end
  end
end

[1, 2, 3, 4, 5].each_with_prevsucc do |prev, item, succ|
  p [prev, item, succ]
end
# => [nil, 1, 2]
#    [1, 2, 3]
#    [2, 3, 4]
#    [3, 4, 5]
#    [4, 5, nil]