From: Sam Duncan Date: 2011-12-15T03:51:44+09:00 Subject: Re: How to pass a list of conditions as parameters On 14/12/11 21:27, Robert Klemme wrote: > On Wed, Dec 14, 2011 at 3:05 AM, Sam Duncan wrote: >> On 14/12/11 14:28, Thescholar Thescholar wrote: >>> I�m unsure how to explain this one so I'll do my best. >>> >>> Technically, I would like to pass an array of numbers and an array of >>> conditions as parameters in a method. The tricky part is that I would >>> like to evaluate each number of that array to each condition of that >>> other array. >>> >>> The reason I would like to achieve something like this is because I plan >>> to change the list of rules/conditions each time I want to call this >>> method. > But what is the desired output? That's crucial for the solution (see below). > >>> Here�s the unworking code so far: >>> >>> (see attachment) >>> >>> Thank you in advance for your valuable support! Any help or hyperlinks >>> with explanations is greatly appreciated! >>> >>> Attachments: >>> http://www.ruby-forum.com/attachment/6838/array_of_conditions.txt >>> >> Nothing pretty or fancy here, but seems to do it? Note, I think the hash >> interpolation is a 1.9.x thing. >> >> >> array_of_numbers = [0, 2, 4, 7, 10, 25] >> >> # these could easily come from a config file/ db/ whatevs >> array_of_eval_conditions = [ "(%{number} == 2)", "(%{number} == 5 and >> %{number} == 5)", "(%{number} != 1)"] >> >> # these could too, but would require a few more hoops >> array_of_lambda_conditions = [lambda {|x| x == 2}, lambda {|x| x == 5 and x >> == 5}, lambda {|x| x != 1}] > Why "more hoops"? There is no point in having conditions in Strings > if they are constant in the script. There is no need for eval here. > > Please note that an more recent versions of Ruby (at least 1.9.3) > lamba implements operator === which is reasonable because then you can > use a lambda as condition in a case expression and with > Enumerable#grep: > > irb(main):004:0> pos = lambda {|x| x>= 0} > => # > irb(main):005:0> vals = [-10,-5,0,5,10] > => [-10, -5, 0, 5, 10] > > irb(main):007:0> vals.each {|v| p v, pos[v], pos === v; case v;when > pos;puts "pos";else puts "not" end} > -10 > false > false > not > -5 > false > false > not > 0 > true > true > pos > 5 > true > true > pos > 10 > true > true > pos > => [-10, -5, 0, 5, 10] > > There do exists ways to do this already, e.g. assuming that conditions > are in an array of lambdas: > > # get all which satisfy all conditions > items.select {|x| conditions.all? {|c| c[v]}} > > # get first which satisfies all conditions > items.find {|x| conditions.all? {|c| c[v]}} > > # get all which satisfy any condition > items.select {|x| conditions.any? {|c| c[v]}} > > # get first which satisfies any condition > items.find {|x| conditions.any? {|c| c[v]}} > > See also Enumerable#reject etc. > > Kind regards > > rober > Having the expressions as strings means you can very easily load them from a data store or config file - the fact they are constant in this /example/ is incidental =] This is not so easy with lambdas which was my point. It also lends itself to a simple boolean expression syntax which can conceivably be configured by a non-coder. The OP does not have 1.9.x by the way. Sam