Brad
Brad

Reputation: 8698

use variable in if statement operator in ruby

I have a variable that contains either '&&' or '||' and I need to use it in an if statement like so.

operator = '&&'

result = 1===1 operator 2===2

#=> result = 1===1 && 2===2

How can I achieve this?

I have tried using #public_send but to no avail.

Any help would be appreciated.

Upvotes: 0

Views: 87

Answers (3)

user1934428
user1934428

Reputation: 22366

You can use public_send, but even if it were allowed with &&, it would not make sense. Note that E1 && E2 shortcircuits, in that E2 is not evaluated if E1 is already falsy. How could this work with public_send?

If you want to have this effect, you have to give up shortcircuiting, which means that you have to use & and | instead of && and ||. If you insist that your variable operator contains something like '&&', and not, say :& (which would make more sense), you could do a

result = (1===1).public_send(operator[0], 2===2)

to use your example for demonstration.

UPDATE: The comment of tadman to my answer made me think that I should warn you about the following trap: Based on your question, I assumed that the arguments you want to connect with your operator are either true or false. In this case, my solution indeed should work. However, if you they can be just any truey or falsy value of some class X, you need to convert them to true or false, because otherwise, the operator may have a different interpretation (for instance, if you operands happen to be integer). Hence, for some general operand_e1_ and e2, which - as is the general rule in Ruby - are supposed to be interpreted als false if it is either false or nil, and is taken as true otherwise, the safe way to calculate your result would be

result = (!!e1).public_send(operator[0], !!e2)

where !! ensures that the expressions are converted to true and false so that the operators & and | can safely be applied.

Upvotes: 0

Les Nightingill
Les Nightingill

Reputation: 6154

You could do it like this:

operator = "&&"
result = eval "1===1 #{operator} 2===2"

does that do what you want?

or if 1===1 is just a placeholder here for some expression, assign the result to a variable, so:

operator = "&&"
a = 1===1
b = 2===2
result = eval "#{a} #{operator} #{b}"

(of course, as commenters have noted, you must pay attention to the security vulnerabilities of eval, e.g. check that the operator variable is either "&&" or "||".)

and if you really want an if statement:

if operator == '&&'
  1===1 && 2===2
elsif operator == '||'
  1===1 || 2===2
else
  # dunno
end

Upvotes: 0

tadman
tadman

Reputation: 211740

The && operator is more of a low-level syntax element than & and | which are method calls. That makes it harder to do.

However, there's two ways:

a = true
b = false
c = true

If you want && equivalence:

[ a, b, c ].all?
# => false
[ a, c ].all?
# => true

If you want || equivalence:

[ a, b, c ].any?
# => true
[ a, b ].any?
# => true
[ b ].any?
# => false

Upvotes: 6

Related Questions