I have a group of classes, all implementing a parse?() class method.
Calling parse?(token) will return the constructed object, if it can
be parsed by this class, or false otherwise.
I want to run a bunch of tokens through these classes, grabbing the
first fit. For example:
elements = tokens.map do |token|
ClassA.parse?(token) or
ClassB.parse?(token) or
ClassC.parse?(token)
end
That works. Now can anyone give me a version of the middle section
that doesn't require I call parse?() 50 times? I want something
close to:
elements = tokens.map do |token|
[ClassA, ClassB, ClassC].find { |kind| kind.parse?(token) }
end
Except that I want the return result of parse?(), instead of the
class that took it.
Thanks for any tips you can offer.
James Edward Gray II
Iterator Fu Failing Me
on 07.01.2006 05:38
Re: Iterator Fu Failing Me
on 07.01.2006 05:41
On Sat, Jan 07, 2006 at 01:36:30PM +0900, James Edward Gray II wrote: > ClassC.parse?(token) > Except that I want the return result of parse?(), instead of the > class that took it. do/end doesn't bind tightly enough for the assignment to 'elements'. Using {} should work. marcel
Re: Iterator Fu Failing Me
on 07.01.2006 05:50
On Jan 6, 2006, at 10:39 PM, Marcel Molina Jr. wrote:
> should work.
Sure it does:
>> numbers = (1..3).map do |n|
?> n * 2
>> end
=> [2, 4, 6]
My problem is not syntax. It's that I can't find a way to iterate to
the result of parse?().
James Edward Gray IIRe: Iterator Fu Failing Me
on 07.01.2006 06:41
Are "Write a new Enumerable method that mimics find but returns the block result instead" or "do a less elegant solution involving assignment" not acceptable solutions?
Re: Iterator Fu Failing Me
on 07.01.2006 07:02
On Sat, 7 Jan 2006, James Edward Gray II wrote: > ClassC.parse?(token) > took it. harp:~ > cat a.rb module Parser module ClassMethods def parse tokens, klasses tokens.map{|token| catch('parse!'){ klasses.each{|klass| klass.parse! token}; nil}} end def parse! token ret = parse?(token) and throw 'parse!', ret end def parse? token return "<#{ token }> parsed by <#{ self }>" if token =~ self::RE end end module InstanceMethods end def self::included other other.module_eval{ extend ClassMethods and include InstanceMethods } end extend ClassMethods and include InstanceMethods end class ClassA include Parser RE = /a/ end class ClassB include Parser RE = /b/ end class ClassC include Parser RE = /c/ end elements = Parser::parse %w( a b c d ), [ClassA, ClassB, ClassC] p elements harp:~ > ruby a.rb ["<a> parsed by <ClassA>", "<b> parsed by <ClassB>", "<c> parsed by <ClassC>", nil] you can probably come up with something shorter - but using catch/throw with parsers is very useful to break of conditions like these. cheers. -a
Re: Iterator Fu Failing Me
on 07.01.2006 07:17
On 2006.01.07 13:36, James Edward Gray II wrote: > ClassC.parse?(token) > end > > That works. Now can anyone give me a version of the middle section > that doesn't require I call parse?() 50 times? I want something > close to: > > elements = tokens.map do |token| > [ClassA, ClassB, ClassC].find { |kind| kind.parse?(token) } > end # Not tested elements = tokens.map {|token| [A, B, C].each {|kind| result = kind.parse?(token) and break result } } > Except that I want the return result of parse?(), instead of the > class that took it. > > Thanks for any tips you can offer. > > James Edward Gray II E
Re: Iterator Fu Failing Me
on 07.01.2006 09:14
Are "Write a new Enumerable method that mimics find but returns the block result instead" or "do a less elegant solution involving assignment" not acceptable solutions?
Re: Iterator Fu Failing Me
on 07.01.2006 11:35
On Sat, 2006-01-07 at 05:36, James Edward Gray II wrote: > ClassC.parse?(token) > end > > That works. Now can anyone give me a version of the middle section > that doesn't require I call parse?() 50 times? I want something I am not certain if this solution fits, but... There is a refactoring named Replace Conditional with Polymorphism that might solve your problem. The idea is that when you have a conditional, you can create a class hierarchy with one subclass for each leg in the conditional. (See http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html for a slightly better explanation.) You already have several different parser classes, and of course you don't need to bother with a class hierarchy, so you could do something like: parser = ParserFactory.create(parser_type) ... elements = tokens.map do |token| parser.parse?(token) end Note that 'parser_type' may well be the class of a token in tokens. This works assuming that all tokens in 'tokens' are of the same type. For example, you have one parser for handling CSV data, another for XML, a third for SGML, a fourth for non-compliant HTML, etc. On the other hand, if each parser class handles a subset of the tokens you get from one type of input, for example you have tokenized an XML file, and have one parser for elements, another for processing instructions, a third for text nodes, etc., you will need something different. A case statement would do the trick: elements = tokens.map do |token| case token when Element ElementParser.parse?(token) when Text TextParser.parse?(token) ... else raise "Unknown token type" end end You can then factor out the case statement into a method named parse?, move the parse? method to a class of it's own, and be back to: elements = tokens.map do |token| ParseEverything.parse?(token) end A while ago I wrote a CSV parser in Java for a talk on Test Driven Design. The Java code got horribly complex, but it struck me that in Ruby I could do this: class Parser def parse(reader, writer) tokenize(reader) { |type| |value| write(type, value, writer) } end end By mixing in tokenize and write methods, it would be possible to build parsers that handle most formats. I hope this helps. /Henrik -- http://www.henrikmartensson.org/ - Reflections on software development
Re: Iterator Fu Failing Me
on 07.01.2006 12:05
On 1/6/06, James Edward Gray II <james@grayproductions.net> wrote: > ClassC.parse?(token) > end > > That works. Now can anyone give me a version of the middle section > that doesn't require I call parse?() 50 times? I want something > close to: > > elements = tokens.map do |token| > [ClassA, ClassB, ClassC].find { |kind| kind.parse?(token) } > end > How about: elements = tokens.map do |token| [ClassA, ClassB, ClassC].inject(false) {|m, kind| m or kind.parse?(token)} end It isn't perfectly efficient but it is short. Brian.
Re: Iterator Fu Failing Me
on 07.01.2006 14:35
James Edward Gray II <james@grayproductions.net> wrote: > ClassC.parse?(token) > Except that I want the return result of parse?(), instead of the > class that took it. > > Thanks for any tips you can offer. > > James Edward Gray II elements = tokens.map do |tok| parsers.inject(false) {|a,par| a=par.parse(tok) and break a} end alternative using a method definition def parse(token) parsers.each {|par| a=par.parse(token) and return a} false end But the best solution is elements = tokens.map do |tok| parsers.detect {|par| par.parse(tok)} end :-) Kind regards robert
Re: Iterator Fu Failing Me
on 07.01.2006 15:50
On Sat, 7 Jan 2006, Eero Saynatkari wrote: >> ClassB.parse?(token) or > > # Not tested > elements = tokens.map {|token| > [A, B, C].each {|kind| > result = kind.parse?(token) and break result > } > } fails when no kind parses. in this case the result will be [[A,B,C]] (the return of each...) regards. -a -- =============================================================================== | ara [dot] t [dot] howard [at] noaa [dot] gov | strong and healthy, | who thinks of sickness until it strikes like lightning? | preoccupied with the world, | who thinks of death, until it arrives like thunder? | -- milarepa ===============================================================================
Re: Iterator Fu Failing Me
on 07.01.2006 16:29
On Sat, 7 Jan 2006, Robert Klemme wrote: > elements = tokens.map do |tok| > parsers.inject(false) {|a,par| a=par.parse(tok) and break a} > end nice. -a -- =============================================================================== | ara [dot] t [dot] howard [at] noaa [dot] gov | strong and healthy, | who thinks of sickness until it strikes like lightning? | preoccupied with the world, | who thinks of death, until it arrives like thunder? | -- milarepa ===============================================================================
Re: Iterator Fu Failing Me
on 07.01.2006 16:45
ara.t.howard@noaa.gov wrote: > On Sat, 7 Jan 2006, Robert Klemme wrote: > >> elements = tokens.map do |tok| >> parsers.inject(false) {|a,par| a=par.parse(tok) and break a} >> end > > nice. Yeah, but #detect is better here. And if *I* say that another solution is bettern than an inject solution... :-) robert
Re: Iterator Fu Failing Me
on 07.01.2006 17:06
On Jan 6, 2006, at 11:36 PM, James Edward Gray II wrote: > That works. Now can anyone give me a version of the middle section > that doesn't require I call parse?() 50 times? I want something > close to: > > elements = tokens.map do |token| > [ClassA, ClassB, ClassC].find { |kind| kind.parse?(token) } > end > > Except that I want the return result of parse?(), instead of the > class that took it. Why not: elements = tokens.map do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| result = kind.parse?(token) } end ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 07.01.2006 17:15
Bob Hutchison <hutch@recursive.ca> wrote: >> Except that I want the return result of parse?(), instead of the >> class that took it. > > Why not: > > elements = tokens.map do |token| > result = nil > [ClassA, ClassB, ClassC].find { |kind| result = kind.parse?(token) } > end Because this won't return the proper value from the block. You need at least to add a line with "result" after the #find. :-) And then it's much more inelegant than using #detect. :-) Kind regards robert
Re: Iterator Fu Failing Me
on 07.01.2006 17:24
ara.t.howard@noaa.gov a écrit : >> ClassA.parse?(token) or >> end > def parse tokens, klasses > module InstanceMethods > end > def self::included other > other.module_eval{ extend ClassMethods and include InstanceMethods } > end > extend ClassMethods and include InstanceMethods > end Could you explain this module ? I think I can understand why you defined a module ClassMethods : to include class methods and not only instace methods. However, I don't understant why the InstanceMethods module ? What do you expect with this module ? Is it just for symetry ? Thanks !
Re: Iterator Fu Failing Me
on 07.01.2006 17:30
Robert Klemme a écrit : >>> end >> end > > > Because this won't return the proper value from the block. You need at > least to add a line with "result" after the #find. :-) And then it's > much more inelegant than using #detect. :-) > > Kind regards > > robert > Well, looking at the documentation of ruby1.8, detect and find are aliases ... is it specific to ruby1.8 or some newer/older version ? Pierre
Re: Iterator Fu Failing Me
on 07.01.2006 17:30
On Sun, 8 Jan 2006, Pierre Barbier de Reuille wrote: > Could you explain this module ? > > I think I can understand why you defined a module ClassMethods : to include > class methods and not only instace methods. > > However, I don't understant why the InstanceMethods module ? What do you > expect with this module ? Is it just for symetry ? yes. just symetry/clarity. is use this pattern alot. even if someone doesn't understand the mechanism i generally assume the 'ClassMethods' and 'InstanceMethods' names will give it away. cheers. -a -- =============================================================================== | ara [dot] t [dot] howard [at] noaa [dot] gov | strong and healthy, | who thinks of sickness until it strikes like lightning? | preoccupied with the world, | who thinks of death, until it arrives like thunder? | -- milarepa ===============================================================================
Re: Iterator Fu Failing Me
on 07.01.2006 18:21
On Jan 7, 2006, at 11:13 AM, Robert Klemme wrote: >>> > > Because this won't return the proper value from the block. You > need at least to add a line with "result" after the #find. :-) cut'n'past-o... oops > And then it's much more inelegant than using #detect. :-) You mean #detect or #select? elements = tokens.select do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| results << kind.parse? (token) } result end And this is kind of handy too... elements = tokens.map do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| result = [token, kind.parse? (token)] } result end > > Kind regards > > robert > > ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 07.01.2006 19:09
Bob Hutchison <hutch@recursive.ca> wrote: >>>> [ClassA, ClassB, ClassC].find { |kind| kind.parse?(token) } >>> (token) } >>> end >> >> Because this won't return the proper value from the block. You >> need at least to add a line with "result" after the #find. :-) > > cut'n'past-o... oops > >> And then it's much more inelegant than using #detect. :-) > > You mean #detect or #select? #detect - because it stops as soon as it has a hit while #select will return an array. We need just the first hit. >> [nil,nil,nil,"w",2,3].find {|x|puts x;x} nil nil nil w => "w" >> [nil,nil,nil,"w",2,3].select {|x|puts x;x} nil nil nil w 2 3 => ["w", 2, 3] > elements = tokens.select do |token| > result = nil > [ClassA, ClassB, ClassC].find { |kind| results << kind.parse? > (token) } > result > end You don't define results and you never assign result another value than nil... > And this is kind of handy too... > > elements = tokens.map do |token| > result = nil > [ClassA, ClassB, ClassC].find { |kind| result = [token, kind.parse? > (token)] } > result > end There's no point in storing token in result because it's unchanged and available as block parameter. Say what you want, find/detect is the most elegant solution. robert
Re: Iterator Fu Failing Me
on 07.01.2006 19:21
On Jan 7, 2006, at 12:19 PM, Bob Hutchison wrote: >>>> elements = tokens.map do |token| >>> [ClassA, ClassB, ClassC].find { |kind| result = kind.parse? > You mean #detect or #select? > elements = tokens.map do |token| > result = nil > [ClassA, ClassB, ClassC].find { |kind| result = [token, > kind.parse?(token)] } > result > end That's wrong! That's twice I've done that. I'm going to go have a nap now. elements = tokens.map do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| result = [token, r = kind.parse?(token)]; r } result end Anyway, I like this version better... elements = tokens.map do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| (result = [token, kind.parse?(token)]).last } result end or this... elements = tokens.map do |token| result = nil [ClassA, ClassB, ClassC].find do |kind| if r = kind.parse?(token) then result = [r, kind, token] end end result || [nil, nil, token] end and you can use "result = (r = kind.parse?(token)) && [r, kind, token]" if you choose Cheers, Bob > Bob Hutchison -- blogs at <http://www.recursive.ca/ > hutch/> > Recursive Design Inc. -- <http://www.recursive.ca/> > Raconteur -- <http://www.raconteur.info/> > xampl for Ruby -- <http://rubyforge.org/projects/ > xampl/> > > > > ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 07.01.2006 19:24
On Jan 7, 2006, at 12:19 PM, Bob Hutchison wrote: > You mean #detect or #select? > > elements = tokens.select do |token| > result = nil > [ClassA, ClassB, ClassC].find { |kind| results << kind.parse? > (token) } > result > end This is wrong too! It should be: elements = tokens.select do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| result = kind.parse?(token) } result end Now, before I dig anymore holes, I'll stop now. ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 07.01.2006 19:27
On Sun, Jan 08, 2006 at 01:13:00AM +0900, Robert Klemme wrote: > >> > Because this won't return the proper value from the block. You need at > least to add a line with "result" after the #find. :-) And then it's much > more inelegant than using #detect. :-) Actually, enum.c: rb_define_method(rb_mEnumerable,"find", enum_find, -1); rb_define_method(rb_mEnumerable,"detect", enum_find, -1); ... (1..10).detect{|x| 10*x > 50} # => 6 ...
Re: Iterator Fu Failing Me
on 07.01.2006 19:54
On Jan 7, 2006, at 7:33 AM, Robert Klemme wrote: > elements = tokens.map do |tok| > parsers.inject(false) {|a,par| a=par.parse(tok) and break a} > end That's what I was looking for. Thank you. > But the best solution is > > elements = tokens.map do |tok| > parsers.detect {|par| par.parse(tok)} > end That's not equivalent. It's actually the same example I showed in my original question message that didn't work. See that post for details, but the short story is that it finds the parsers that did the conversion, not the parsed elements I was looking for. James Edward Gray II
Re: Iterator Fu Failing Me
on 07.01.2006 20:15
On Jan 7, 2006, at 1:08 PM, Robert Klemme wrote: > w > => "w" >>> [nil,nil,nil,"w",2,3].select {|x|puts x;x} > nil > nil > nil > w > 2 > 3 > => ["w", 2, 3] > The trouble is that detect returns the 'x' not the result of processing x successfully (or, in terms of the original post, the class that accepts the token not the result of the #parse? method). That's why you have to capture the result in the block. Map returns the result of processing. >> elements = tokens.select do |token| >> result = nil >> [ClassA, ClassB, ClassC].find { |kind| results << kind.parse? >> (token) } >> result >> end > > You don't define results and you never assign result another value > than nil... Sorry, I've 'corrected' myself in a mail I just sent out. (My email is suffering long delays today, and my mind isn't working all that quickly either I think) This is what I had intended with the "<< results" is: results = [] tokens.each do |token| # use find over the collection of classes to find the one that successfully parses the # token. Find will return the class, not the result of #parse?, so capture that result # by using a closure on result (Note: result must appear outside of and before the block. # Collect each result in results. result = nil [ClassA, ClassB, ClassC].find { |kind| result = kind.parse?(token)} results << result if result end If you also want the nil results then you can use: elements = tokens.map do |token| result = nil [ClassA, ClassB, ClassC].find { |kind| result = kind.parse?(token)} result end > Say what you want, find/detect is the most elegant solution. > Only they return the wrong things. > robert > > ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 07.01.2006 20:43
On 2006.01.07 23:49, ara.t.howard@noaa.gov wrote: > >> elements = tokens.map do |token| > >> [ClassA, ClassB, ClassC].find { |kind| kind.parse?(token) } > > [[A,B,C]] (the return of each...) You are (of course) absolutely right, it should be 'return result' coupled with a default nil/false at the end. One of these days I will learn not to write mail at four in the morning :) > regards. > -a E
Re: Iterator Fu Failing Me
on 07.01.2006 23:44
Bob Hutchison <hutch@recursive.ca> wrote: >> nil >> > > The trouble is that detect returns the 'x' not the result of > processing x successfully (or, in terms of the original post, the > class that accepts the token not the result of the #parse? method). > That's why you have to capture the result in the block. Map returns > the result of processing. Aargh! I shoul've tested more carefully. Yes you're completely right. But the inject version still works, I think that's then my favourite. elements = tokens.map do |tok| parsers.inject(false) {|a,pars| a = pars.parse? tok and break a} end Thanks for correcting me! robert
Re: Iterator Fu Failing Me
on 08.01.2006 00:08
Hi -- On Sun, 8 Jan 2006, ara.t.howard@noaa.gov wrote: > yes. just symetry/clarity. is use this pattern alot. even if someone > doesn't understand the mechanism i generally assume the 'ClassMethods' and > 'InstanceMethods' names will give it away. Wouldn't it be clearer just to write instance methods for a module? It feels a bit like you're creating a kind of second skin for a system that already does this. David -- David A. Black dblack@wobblini.net "Ruby for Rails", from Manning Publications, coming April 2006! http://www.manning.com/books/black
Re: Iterator Fu Failing Me
on 08.01.2006 15:08
On Jan 7, 2006, at 5:43 PM, Robert Klemme wrote: >>> nil >>> => ["w", 2, 3] > favourite. > > elements = tokens.map do |tok| > parsers.inject(false) {|a,pars| a = pars.parse? tok and break a} > end Personally, I don't like the break. It'd be very nice if there were equivalent operations returning the result of the calculation rather than the object. > > Thanks for correcting me! Sorry for the brutally finger-tied attempts at communication :-) > > robert > > ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 09.01.2006 01:58
Perhaps I'm missing the point, but wouldn't the following work: (?)
elements = tokens.map do |token|
val = nil
[ClassA, ClassB, ClassC].find { |kind| val = kind.parse?(token) }
val
end
JustinRe: Iterator Fu Failing Me
on 09.01.2006 02:10
On Jan 8, 2006, at 6:58 PM, jwesley wrote: > Perhaps I'm missing the point, but wouldn't the following work: (?) > > elements = tokens.map do |token| > val = nil > [ClassA, ClassB, ClassC].find { |kind| val = kind.parse?(token) } > val > end It works just fine, yes. Just doesn't feel very Rubyish to me. <shrugs> James Edward Gray II
Re: Iterator Fu Failing Me
on 09.01.2006 02:55
On Mon, 09 Jan 2006 01:09:23 -0000, James Edward Gray II <james@grayproductions.net> wrote: > It works just fine, yes. Just doesn't feel very Rubyish to me. <shrugs> > Not sure this is more Rubyish (seems a bit line-noisy) but: class Parser class << self def parse?(tok) tok.downcase if tok == self.name end end end class One < Parser; end class Two < Parser; end class Three < Parser; end parsers = [One, Two, Three] tokens = ['One','Two','One','siz','Four','Two'] r = tokens.inject [] do |r,token| r << (parsers.zip([token] * parsers.length).detect { |p,tok| p.parse? tok } || [])[0] end p r Seems to work. It's *terribly* inefficient though I guess.
Re: Iterator Fu Failing Me
on 09.01.2006 03:13
On Mon, 09 Jan 2006 01:45:11 -0000, Ross Bamford <rosco@roscopeco.remove.co.uk> wrote: > Not sure this is more Rubyish (seems a bit line-noisy) but: > For crying out loud I've done it again }:-{. Please ignore me.
Re: Iterator Fu Failing Me
on 09.01.2006 03:25
On Mon, 09 Jan 2006 01:45:11 -0000, Ross Bamford <rosco@roscopeco.remove.co.uk> wrote: >>> val >>> end >> >> It works just fine, yes. Just doesn't feel very Rubyish to me. >> <shrugs> >> > > Not sure this is more Rubyish (seems a bit line-noisy) but: > This one looks worse, but at least really does seem to work this time: r = tokens.inject([]) do |arr,token| arr << parsers.zip([token]*parsers.length).inject(nil) do |out,pt| out or pt[0].parse?(pt[1]) end end slotted into the code before and it gives: ["one", "two", "one", nil, nil, "three"] Sorry about that.
Re: Iterator Fu Failing Me
on 09.01.2006 03:40
On Mon, 09 Jan 2006 02:17:26 -0000, Ross Bamford <rosco@roscopeco.remove.co.uk> wrote: > r = tokens.inject([]) do |arr,token| > arr << parsers.zip([token]*parsers.length).inject(nil) do |out,pt| > out or pt[0].parse?(pt[1]) > end > end > Damn it... == r = tokens.inject([]) do |arr,token| arr << parsers.inject(nil) { |out,p| out or p.parse?(token) } end Now I'm really done. Promise.
Re: Iterator Fu Failing Me
on 09.01.2006 14:05
On Jan 8, 2006, at 9:38 PM, Ross Bamford wrote: > Damn it... > > == > > r = tokens.inject([]) do |arr,token| > arr << parsers.inject(nil) { |out,p| out or p.parse?(token) } > end > > Now I'm really done. Promise. This thread is jinxed. :-) > > -- > Ross Bamford - rosco@roscopeco.remove.co.uk > ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Re: Iterator Fu Failing Me
on 09.01.2006 19:47
why not write a new iterator: it will probably be useful again sometime:
module Enumerable
def find_first_result
each {|item| result = yield item; return result if result }
nil
end
end
irb(main):075:0> tokens = %w( adam codes in ruby )
=> ["adam", "codes", "in", "ruby"]
irb(main):076:0> classes = [/a/, /b/, /c/]
=> [/a/, /b/, /c/]
irb(main):077:0> elements = tokens.map do |token|
irb(main):078:1* classes.find_first_result {|kind| kind =~ token}
irb(main):079:1> end
=> [0, 0, nil, 2]
-AdamRe: Iterator Fu Failing Me
on 10.01.2006 01:29
On Sun, 8 Jan 2006 dblack@wobblini.net wrote: > Wouldn't it be clearer just to write instance methods for a module? It > feels a bit like you're creating a kind of second skin for a system that > already does this. generally i do just this. however, i've found it extremely useful to be able to do include SomeModule::InstanceMethods # mixin only instance methods extend SomeModule::ClassMethods # mixin only class methods include SomeModule # mixin InstanceMethods and extend with ClassMethods via # over-ridden self::included when factoring out code in large systems. regards. -a -- =============================================================================== | ara [dot] t [dot] howard [at] noaa [dot] gov | strong and healthy, | who thinks of sickness until it strikes like lightning? | preoccupied with the world, | who thinks of death, until it arrives like thunder? | -- milarepa ===============================================================================
