How to pass a list of conditions as parameters

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.

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!

On 14/12/11 14:28, Thescholar Thescholar wrote:

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}]

for each number and condition, is it true when eval’ed?

def test_function_with_eval(numbers, conditions)
numbers.each { |n|
conditions.each { |c|
puts ((eval(c%{:number=>n}))?“condition IS MET!”:“condition is
NOT met”)
}
}
end

for each number and condition, is it true when called?

def test_function_with_lambdas(numbers, conditions)
numbers.each { |n|
conditions.each { |c|
puts ((c.call(n))?“condition IS MET!”:“condition is NOT met”)
}
}
end

puts “With eval!”
test_function_with_eval(array_of_numbers, array_of_eval_conditions)
puts “With lambdas!”
test_function_with_lambdas(array_of_numbers, array_of_lambda_conditions)

Sam

On 14/12/11 16:32, Thescholar Thescholar wrote:

That is interpolating hash values in a string based on their key - it
was just an easy way to get that number in the string twice and only
specify it once =]
It is new in 1.9.x I believe and is similar to functionality found in
python string interpolation with dicts.

Hope that helps

Sam

Thank you very Sam! It seems there are still a lot more I need to learn
though.

For example, could you tell me where I could I learn more about this
part within the array? -----> %{number}

What keyword do I need to type on google to find more information about
this process?

Thank you again!

The technology I’m using uses a version inferior to 1.9.x, fortunately
your example with lambda works like magic.

Your help was extremely helpful Sam! Thank you very much and Happy
Holidays! God Bless you (and every other members of this forum)!

On Wed, Dec 14, 2011 at 3:05 AM, Sam D. [email protected]
wrote:

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).

Nothing pretty or fancy here, but seems to do it? Note, I think the hash
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}
=> #<Proc:0x100e300c@(irb):4 (lambda)>
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

That works with 1.9.2 :

require ‘pp’

def acond(avalues,aconditions)
avalues.map { |n| [n,aconditions.map { |blk| blk.call(n) }] }
end

an = [0, 2, 4, 7, 10, 25, 6]
ac = [
proc { |number| number == 2},
proc { |number| number == 5 or number == 6},
proc { |number| number!=1}
]

pp acond(an,ac)

[[0, [false, false, true]],
[2, [true, false, true]],
[4, [false, false, true]],
[7, [false, false, true]],
[10, [false, false, true]],
[25, [false, false, true]],
[6, [false, true, true]]]

On 14/12/11 21:27, Robert K. wrote:

On Wed, Dec 14, 2011 at 7:51 PM, Sam D. [email protected]
wrote:

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 =]

But it helps understanding to explicitly mention this fact. That was
the whole point of the exercise.

The OP does not have 1.9.x by the way.

I think that was only relevant for my tangential remark about lambda
and === anyway.

Cheers

robert