Reputation: 8698
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
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
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
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