#-- # merlin/each.rb : merlin-each 0.1.0 # # Copyright (C) 2004 Merlin Hughes # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #++ # JSTL-like each-with-status mixin for Array, Hash and ENV. # # Disclaimer: I know neither JSTL nor Ruby. And I don't know # how to make this a generic mixin for Enumerable things. # # array.each_with_status { |item, status| block } # - Executes the block for each item in the # Array, with a status object holding iterator # information: # array.reverse_each_with_status { |item, status| block } # - As expected. # # hash.each_with_status { |key, value, status| block } # - Executes the block for each key/value pair in the # Hash, with a status object holding iterator # information: # hash.each_key_with_status { |key, status| block } # hash.each_pair_with_status { |key, value, status| block } # hash.each_value_with_status { |value, status| block } # - As expected. # # ENV.each*_with_status # - As expected. # # Status object methods: # first? - true for the first item in the enumeration # last? - true for the last item in the enumeration # index - zero-based index # count - one-based index # length - datastructure length # to_s - string representation # # require 'merlin/each' # a = [ 'foo', 'bar', 'baz' ] # a.each_with_status { |value, status| # if status.first? # print value # elsif !status.last? # print ", ", value # else # print " or ", value # end # } # produces: `foo, bar or baz' # # WARNING: clashes with Hiroyuki Komatsu's taiyaki.rb module Merlin class Status attr_reader :index, :length def initialize(length) @length = length @index = -1 end def first? @index == 0 end def last? @index == @length -1 end def count @index + 1 end def next @index += 1 self end def to_s "first? #{first?}, last? #{last?}, index #{index}, count #{count}, length #{length}" end end # class Status end # I don't know how to make this work for Array.each (one parameter) # and Hash.each (two parameters), so this isn't a generic mixin.. # # module EachWithStatus # def each_with_status # status = Status.new(self.length) # self.each { |value| # yield(value, status.next) # } # end # def each_with_status # end # module EachWithStatus module ArrayEach def each_with_status status = Merlin::Status.new(self.length) self.each { |value| yield(value, status.next) } end # def each_with_status def reverse_each_with_status status = Merlin::Status.new(self.length) self.reverse_each { |value| yield(value, status.next) } end # def reverse_each_with_status end # module ArrayEachWithStatus class Array include ArrayEach end # class Array module HashEach def each_with_status status = Merlin::Status.new(self.length) self.each { |key, value| yield(key, value, status.next) } end # def each_with_status alias :each_pair_with_status :each_with_status def each_key_with_status status = Merlin::Status.new(self.length) self.each_key { |key| yield(key, status.next) } end # def each_key_with_status def each_value_with_status status = Merlin::Status.new(self.length) self.each_value { |value| yield(value, status.next) } end # def each_value_with_status end # module HashEachWithStatus class Hash include HashEach end # class Hash ENV.extend HashEach