From: Robert Klemme Date: 2007-06-11T05:45:06+09:00 Subject: Re: Passing block to Proc#call On 10.06.2007 18:25, Erwin Abbott wrote: > On 6/10/07, Robert Klemme wrote: >> > x.call(*%w[cats dogs ones twos threes]) do |*words| >> > puts words.last # output: thre >> > end >> >> Why do you need x here? Do you need to pass it around? Can you show a >> bit more of the picture? > > I ended up refactoring, but earlier I was parsing some text by > associating an array of attributes (like, [/a/, /b/, /c$/] that might > match the first 3 words) with a block that processed the matching > text, and then moved the position in the string forward by 3 words. I > tried wanted to be able to do this like: Did I understand that properly, you want to process three words at a time and then the next three words? Then you could do require 'enumerator' words.each_slice 3 do |w1,w2,w3| ... end or words.each_slice 3 do |three_words| patterns.each do |rxs, process| if rxs.to_enum(:zip, three_words).all? {|rx, wd| rx =~ wd} process[three_words] break end end end It's still unclear to me how exactly you want the matching to work. Are all your "attributes" matched against all three words? Do you positional matches? In the code all rx's are matched against words in the same position and if all match the block is invoked on the words. > match = proc do |*regexs| > if words[position..position+regexs.size] match given regexs > parsed << yield *words[ .. ] > end > end > > words = %w[the quick brown egg jumped under the slow zebra] > parsed = [] > > while position < words.size > match.call(//, /ed/, //) do {|a, b, c| "#{a} #{b.upcase} #{c}" } > match.call(/the/, //) do {|a, b| "the #{b.upcase}" } > > # increment position somewhere, maybe in match..? this was messy > end > > # parsed => [the QUICK brown egg JUMPED under the SLOW zebra] > > # where the matched strings were "the quick", "egg jumped under" > # and "the slow" > > Anyway, it turned out that was messy even if I didn't have trouble > passing a block. Instead I made a method scanner(*regexs, &block) that > stores everything in an array, then later another method runs through > the list and does the actual work, where it keeps track of the > position and knows if it made a match or not. Should've slept on it > before I mailed the list! > >> There is no other compatible way than to explicitly pass a lambda / proc >> as argument in 1.8.x: > > I forgot about passing a lambda/proc as a "normal" parameter... that > would've worked though the syntax isn't as cute. > > Thanks for your help Robert and Axel! > I still think you're not yet there. Kind regards robert