each で隣の要素を参照

おぉ?こういうのは Enumerable モジュールに適当にメソッド追加とかでどうにでもなりそうな気がする。

module Enumerable
   def each_with_neighbor
      window = [:none, :none, :none]
      each do |item|
         window.push item
         window.shift

         if window[1] != :none
            yield *window
         end
      end

      window.push :none,
      window.shift
      if window[1] != :none
         yield *window
      end
   end
end

(0..10).each_with_neighbor do |prev, item, succ|
   puts "#{prev} #{item} #{succ}"
end

てな感じでいいんでないかなぁ。変態的なのが好みならこういうのとか。なんかいろいろまずい気がするのでおすすめできない。

module Enumerable

   class Window
      attr_reader :prev, :succ
      def initialize(val, prev, succ)
         @val, @prev, @succ = val, prev, succ
      end

      def method_missing(name, *args)
         @val.send(name, *args)
      end

      def ==(x)
         @val == x
      end

      def inspect
         @val.inspect
      end
   end

   def each_with_neighbor(&block)
      def yield_with_neighbor(window, &block)
         item = Window.new(window[1], window[0], window[2])
         item.instance_eval(&block)
      end

      window = [:none, :none, :none]
      each do |item|
         window.push item
         window.shift

         if window[1] != :none
            yield_with_neighbor(window, &block)
         end
      end

      window.push :none,
      window.shift
      if window[1] != :none
         yield_with_neighbor(window, &block)
      end
   end
end

(0..10).each_with_neighbor do |i|
   p [prev, i, succ]
end

Array だけでいいなら zip を使うのが手軽ではある。

class Array
   def each_with_neighbor
      l = length
      ([nil] + self[0, l - 1]).zip(self, self[1, l - 1] + [nil]).each do |prev, item, succ|
         yield prev, item, succ
      end
   end
end

(0..10).to_a.each_with_neighbor do |prev, item, succ|
   p [prev, item, succ]
end

いや、ていうか Array なら each_with_index で index を使って前後を取得すればいいのか。
組み込み変数を使うのはユーザレベルでスレッドローカル変数がないとマルチスレッド環境がなんとも。