Monday, 15 April 2013

class - Guidance on how to implement certain problems in Ruby -



class - Guidance on how to implement certain problems in Ruby -

for class numberset, have define [] method takes 1 argument, uses filter select members of set , returns new set containing elements.

for example, have

filter.new { |number| number.even? }

and

signfilter.new(:non_negative)

which classes must construct.

i have define & , | operators work filters. along lines of

numbers[signfilter.new(:non_negative) & filter.new { |number| number.even? }]

the class far is:

class numberset include enumerable def initialize @arr=[] end def each (&block) @arr.each |member| block.call (member) end end def << number @arr<<number unless @arr.include?(number) end end

for filter think works:

class filter def initialize yield end end

my biggest problem [], $and | parts, have no thought how do.

what want accomplish :

numbers = numberset.new [-3, -2, -1, 0, 1, 2, 3, 4, 5].each |number| numbers << number end numbers[signfilter.new(:non_negative) & filter.new { |number| number.even?}].to_a #=>[0, 2, 4]

i think should it.

code

signfilter class

class signfilter def initialize(sign) @sign = sign end def filter case @sign when :negative -> { < 0 } when :positive -> { > 0 } when :non_negative -> { >= 0 } when :non_positive -> { <= 0 } when :zero -> { i.zero? } end end end

filter class

class filter attr_reader :filter def initialize &filter @filter = filter end end

numberset class

class numberset def initialize arr @arr = arr end def process(op, sf, f) sign_filter = sf.filter filter = f.filter @arr.send(op).each { |e| sign_filter.call(e) } .send(op).each { |e| filter.call(e) } end end

examples

sf = signfilter.new :negative f = filter.new { |number| number.even? } ns = numberset.new [-3, -2, -1, 0, 1, 2, 3, 4, 5] ns.process(:reject, sf, f) #=> [1, 3, 5] sf = signfilter.new :non_negative f = filter.new { |number| number % 3 == 0 } ns = numberset.new [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6] ns.process(:select, sf, f) #=> [0, 3, 6]

explanation

blocks not objects, can't pass them around. can converted procs, however, objects (instances of class proc), , hence can passed. need understand procs (and lambdas, type of proc). here explanation. (aside: 1 thing that's little confusing procs multitude of ways can invoked. example, if p -> { 3*i }, p.call(2), p.yield(2), p[2] , p.(2) homecoming value 6.)

here happening:

an instance sf of signfilter class created passing symbol denoting signs of elements of array selected or rejected (:negative, :non_negative , on). symbol saved in instance variable @sign. the signfilter class has method filter returns lambda based on value of @sign. an instance of filter class created passing block received proc , saved instance variable @filter, has read accessor. an instance of numberset class created passing array, saved instance variable @arr. numberset#process passed 3 arguments: enumerable method :reject or :select (saved op), signfilter instance (sf) , filter instance (f). within numberset#process, @arr sent op, creates enumerator (arr.reject or arr.select). the signfilter lambda called on each element of enumerator. array comprised of subcollection of @arr returned. the returned array sent op, creating reject or select enumerator. the filter proc called on each element of new enumerator, causing desired array returned.

considering both reject , select not necessary (either do), have been simpler replace .send(op) in numberset#process with, say, reject, chose way illustrate generalization.

notice easy generalize numberset#process process(sf,f,o), where, now, sf , f provide filters , o instance of operation class specifies proc send filtered subcollection of @arr invoke enumerable method block (map, group_by , on).

ruby class filter

No comments:

Post a Comment