I have encountered a weird situation while I’m writing a piece of code in Ruby. Here is the sample code extracting the essence of the problem I have faced. First, I tried to get the matching result with a line of code as follows.
p1 = /hello/
p2 = /world/
s = "hello, world"
if m1 = s.match(p1) || m2 = s.match(p2)
puts "m1=#{m1}"
puts "m2=#{m2}"
end
It shows:
m1=hello
m2=
Oops, I forgot that the logical operator ||
does the short-circuit evaluation. It makes m2
nil. What I wanted to do was checking both regular expressions are matching with the given string. Here is the correct one.
if m1 = s.match(p1) && m2 = s.match(p2)
puts "m1=#{m1}"
puts "m2=#{m2}"
end
But it shows:
m1=world
m2=world
Hmm, the result was unexpected. Why is m1
assigned by the outcome of p2
pattern? I expected that the result of the matching of p1
pattern is assigned to m1
and so forth for m2
. Is the precedence of the operators correctly working?
According to the Ruby operator precedence, the logical operator &&
precedes the assignment operator =
. Therefore, the evaluation order of the previous code should be same as:
if (m1 = s.match(p1)) && (m2 = s.match(p2))
puts "m1=#{m1}"
puts "m2=#{m2}"
end
Obviously, its outcome is expected.
m1=hello
m2=world
In reality, the evaluation looks like:
if m1 = (s.match(p1) && m2 = s.match(p2))
puts "m1=#{m1}"
puts "m2=#{m2}"
end
The logical operator follows the assignment to m2
.
Since the result seems weird and I’m still not sure the mechanism behind this behavior, I posted one question in StackOverflow
I would very much appreciate it if you could find the answer to this problem. Thanks!