################################## | |
### SCROLL DOWN FOR AN EXAMPLE ### | |
################################## | |
module Enumerable | |
# your each_with_position method | |
def each_pos &block | |
EachWithPosition.each(self, &block) | |
end | |
end | |
class EachWithPosition | |
attr_reader :index | |
class << self | |
def each *a, &b | |
handler = self.new(*a, :each, &b) | |
end | |
end | |
def initialize collection, method, &block | |
@index = 0 | |
@item, @prev, @next = nil | |
@collection = collection | |
@callback = block | |
self.send(method) | |
end | |
def count | |
@collection.count | |
end | |
alias_method :length, :count | |
alias_method :size, :count | |
def rest | |
count - position | |
end | |
def first? | |
@index == 0 | |
end | |
def last? | |
@index == (count - 1) | |
end | |
def wrapped? | |
!first? && !last? | |
end | |
alias_method :inner?, :wrapped? | |
def position | |
@index + 1 | |
end | |
def prev | |
@prev | |
end | |
def next | |
@next | |
end | |
def current | |
@item | |
end | |
alias_method :item, :current | |
alias_method :value, :current | |
def call | |
if @callback.arity == 1 | |
@callback.call(self) | |
else | |
@callback.call(@item, self) | |
end | |
end | |
def each | |
@collection.each_cons(2) do |e, n| | |
@prev = @item | |
@item = e | |
@next = n | |
self.call | |
@index += 1 | |
# fix cons slice behaviour | |
if last? | |
@prev, @item, @next = @item, @next, nil | |
self.call | |
@index += 1 | |
end | |
end | |
end | |
end | |
("a".."m").to_a.each_pos do |e| | |
puts "Char\tfirst?\tlast?\tprev\tnext\twrapped?\tindex\tposition" if e.first? | |
print "#{e.item}\t" | |
print "#{e.first?}\t" | |
print "#{e.last?}\t" | |
print "#{e.prev}\t" | |
print "#{e.next}\t" | |
print "#{e.wrapped?}\t\t" | |
print "#{e.index}\t" | |
puts "#{e.position}\t" | |
end | |
# Char first? last? prev next wrapped? index position | |
# a true false b false 0 1 | |
# b false false a c true 1 2 | |
# c false false b d true 2 3 | |
# d false false c e true 3 4 | |
# e false false d f true 4 5 | |
# f false false e g true 5 6 | |
# g false false f h true 6 7 | |
# h false false g i true 7 8 | |
# i false false h j true 8 9 | |
# j false false i k true 9 10 | |
# k false false j l true 10 11 | |
# l false false k m true 11 12 | |
# m false true l false 12 13 | |
{}.tap {|h| ("a".."m").each_with_index {|c, i| h[c] = i}}.each_pos do |(k, v), e| | |
puts "KV\tChar\t\tfirst?\tlast?\tprev\t\tnext\t\twrapped?\tindex\tposition" if e.first? | |
print "#{k} => #{v}\t" | |
print "#{e.item}\t" | |
print "#{e.first?}\t" | |
print "#{e.last?}\t" | |
print "#{e.prev || "\t"}\t" | |
print "#{e.next || "\t"}\t" | |
print "#{e.wrapped?}\t\t" | |
print "#{e.index}\t" | |
puts "#{e.position}\t" | |
end | |
# KV Char first? last? prev next wrapped? index position | |
# a => 0 [:a, "0"] true false [:b, "1"] false 0 1 | |
# b => 1 [:b, "1"] false false [:a, "0"] [:c, "2"] true 1 2 | |
# c => 2 [:c, "2"] false false [:b, "1"] [:d, "3"] true 2 3 | |
# d => 3 [:d, "3"] false false [:c, "2"] [:e, "4"] true 3 4 | |
# e => 4 [:e, "4"] false false [:d, "3"] [:f, "5"] true 4 5 | |
# f => 5 [:f, "5"] false false [:e, "4"] [:g, "6"] true 5 6 | |
# g => 6 [:g, "6"] false false [:f, "5"] [:h, "7"] true 6 7 | |
# h => 7 [:h, "7"] false false [:g, "6"] [:i, "8"] true 7 8 | |
# i => 8 [:i, "8"] false false [:h, "7"] [:j, "9"] true 8 9 | |
# j => 9 [:j, "9"] false false [:i, "8"] [:k, "10"] true 9 10 | |
# k => 10 [:k, "10"] false false [:j, "9"] [:l, "11"] true 10 11 | |
# l => 11 [:l, "11"] false false [:k, "10"] [:m, "12"] true 11 12 | |
# m => 12 [:m, "12"] false true [:l, "11"] false 12 13 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment