From: Joel VanderWerf Date: 2001-11-04T04:51:10+09:00 Subject: [ruby-talk:24283] Re: Too much eval evil? (tell me why I shouldn't do this) mrcode@mediaone.net wrote: > a = [(0..20), (43..150), ['z','yz','xyz','xz','zz']] > cascade(a) do |width, length, hight| > puts "width is: #{width}, length is: #{length}, hight is: #{hight}" > end > > But overall I think Joel VanderWerf's Enumerable tools are probably better > thought out and implemented than my version. I'll probably be adding that > to my list of useful libraries. There's something a little different about the product operator I defined. It returns a new "proxy" enumerable which delegates to the given ones (the factors of the product). So, in the current version (**), you can't just pass a block to it, you have to call each on the return value of product: require 'enum/op' include EnumerableOperator a = [(0..20), (43..150), ['z','yz','xyz','xz','zz']] product(*a).each do |width, length, hight| puts "width is: #{width}, length is: #{length}, hight is: #{hight}" end However, this allows use of 'for', which is very readable: for width, length, hight in product(*a) puts "width is: #{width}, length is: #{length}, hight is: #{hight}" end Also, you can chain with other iterations without generating the intermediate collection, which may be large: product(*a).select { |w, l, h| w > 18 && l < 45 && h == 'zz' } ---- (**) With a small change, you can pass a block and have product behave like cascade. Just define product as follows: def product(*factors, &block) if block Product.new(*factors).each &block else Product.new(*factors) end end Now you can leave out the ".each": product(*a) do |width, length, hight| puts "width is: #{width}, length is: #{length}, hight is: #{hight}" end This'll go in the next version. -- Joel VanderWerf California PATH, UC Berkeley mailto:vjoel@path.berkeley.edu Ph. (510) 231-9446 http://www.path.berkeley.edu FAX (510) 231-9512