Keyword for exclusive or in ruby? - ruby

Does Ruby have a plain-English keyword for exclusive or, like they have "and" and "or"? If not, is this because exclusive or doesn't allow evaluation short-cutting?

No it doesn't, you can only use ^.
Don't know why there isn't particularly, may just be because it isn't as commonly used.

I ran into an issue because the '^' operator acts bitwise on numbers,
true ^ 1
=> false
1 ^ true
TypeError: can't convert true into Integer
true ^ 1
so my workaround was:
( !!a ^ !!b ) where the double-bang coerces them into booleans.
!!1 ^ !!true
=> false
!!1 ^ !!false
=> true

Firstly, I don't think shortcircuiting can sensibly apply to XOR: whatever the value of the first operand, the second needs to be examined.
Secondly, and, &&, or and || use shortcircuiting in all cases; the only difference between the "word" and "symbol" versions is precedence. I believe that and and or are present to provide the same function as perl has in lines like
process_without_error or die
I think the reason for not having a xor named function is probably that there's no point in a low-precedence operator in this case and that it's already a confusing enough situation!

Try ^
true ^ false #=> true
true ^ true #=> false
false ^ false #=> false
No plain english equivalent operator though.

As an alternative to Matt Van Horn's double negation trick for using XOR on arbitrary types, you can chain another XOR test, starting with nil. i.e.:
!!foo ^ !!bar
is equivalent to
nil ^ foo ^ bar
This looks neater to my eye, and I suppose requires one less logical operation

Any implementation of xor won't allow short circuiting. Both expressions need to be evaluated no matter what.
Ruby does provide the ^ operator, but this will choke on truthy values. I've implemented a function to handle the cases where I want an xor that behaves more like and and or:
def xor(a,b)
(a and (not b)) or ((not a) and b)
end
Unlike ^, this function can be used in situations similar to the following:
xor("hello".match(/llo/), false) # => true
xor(nil, 1239) # => true
xor("cupcake", false) # => false

John's answer appears incorrect. In irb with 1.9.3, xor("cupcake", false) returns true, as you'd expect.
1.9.3-p429 :104 > def xor(a,b)
1.9.3-p429 :105?> (a and (not b)) or ((not a) and b)
1.9.3-p429 :106?> end
=> nil
1.9.3-p429 :107 > xor(false, true)
=> true
1.9.3-p429 :108 > xor("cupcake", false)
=> true

Related

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

Why does Ruby have no !== operator?

Is all equality in Ruby is "strict", analogous to === in PHP? I notice that there is a === operator in Ruby but it does something different.
=== is not an equality operator!
Not.
But, what is it?
You might be familiar with === as an equality operator in Javascript and PHP, but this just not an equality operator in Ruby and has fundamentally different semantics from other languages.
So what does === do?
=== is the pattern matching operator!
=== matches regular expressions
=== checks range membership
=== checks being instance of a class
=== calls lambda expressions
=== sometimes checks equality, but mostly it does not
So how does this madness make sense?
Enumerable#grep uses === internally
case when statements use === internally
That is why you can use regular expressions and classes and ranges and even lambda expressions in a case when statement.
Some examples
case value
when /regexp/
# value matches this regexp
when 4..10
# value is in range
when MyClass
# value is an instance of class
when ->(value) { ... }
# lambda expression returns true
when a, b, c
# value matches one of a, b, c with `===`
when *array
# value matches an element in array with `===`
when x
# values is equal to x unless x is one of the above
end
All these example work with pattern === value too, as well as with grep method.
I can only guess why there's no !== method but Tadman's intuition seems spot on, === is mostly used indirectly through case when and grep and thus likely didn't seem to need an explicit inverse operator. Most style guides for production code ban the use of === operator anyway.
If you are looking for other equality operators, check .eql? and .equal?
Ruby doesn't need a strict ===-type operator because the default comparator == is already quite strict, unlike PHP and others. It's not often the case any sort of conversion is done, so the cases where it is performed stand out as exceptional:
0 == ""
# => false
0 == "0"
# => false
"" == " "
# => false
0 == nil
# => false
0 == 0.0
# => true
In fact when you do use === you're often asking for trouble by being overly specific or inviting unexpected behaviour:
"" === String
# => false
String === ""
# => true
String === Object
# => false
Object === String
# => false
The meaning of === is defined by various classes in different ways to mean things often unrelated to "equality". It's just a shorthand like << is at times. Object === String is actually Object.===(String) which is why it produces different results from String.===(Object). In that case it means "is equal to or a derived class of...".
It's because of this relative rarity that !== doesn't really need to exist in the first place. === is often used only indirectly, as it's the default method for comparing things via a case statement.
Ah... after digging deeper I think I answered my own question. Ruby has .eql? .equal? link
Ruby's equality is not strict using ==, at least not like === in JavaScript. Ruby has stricter equality methods, such as eql? and equal?, but the === is not for strict equality. The === method is called the subsumption operator. It's most used implicitly in case statements. This is to say that
case a
when b ...
when c ...
else ...
end
is equivalent to
if b === a
...
elsif c === a
...
else
...
end
Having said that, !== could exist, but instead it is just left for the user to do !(a === b). Note that === is not commutative as in a === b is not the same as b === a.

What's the boolean value of `0` in Ruby?

After looking at the behavior of these expressions:
1 and 0 #=> 0
0 and 1 #=> 1
1 and true #=> true
0 and true #=> true
to me, it is more like ruby returns the right side value of a logic gate regardless of the evaluated result of the logical expression. I am looking for the reason for it.
Two things you need to know:
and (and &&) returns the first operand if it's false, otherwise returns the second operand.
Anything other than false and nil is true, including 0.
TL;DR
Ruby is behaving properly, but might be confusing if you're coming from another language. This confusion is most often caused by:
Not understanding truth-values and false-values in Ruby, especially when evaluating the truthiness of control expressions.
Using a flow-control operator like and to test for equality instead of ==.
Misunderstanding how the parser sees your "comparison" as two separate expressions.
To fix the problem you describe, use an equality operator to test for truthiness. A more detailed explanation follows.
Ruby Returns the Last Expression Evaluated
In Ruby, every expression returns a value. When you evaluate expressions like:
1 and 0 #=> 0
you aren't checking the truthiness of each expression as you would be with an actual Boolean-returning expression such as:
!!(1 and 0) #=> true
Instead, you are simply evaluating two expressions in sequence, unless the first expression evaluates as nil or false and short-circuits the evaluation. Either way, Ruby returns the value of the last expression evaluated. In this case, you could get the same result with:
1; 0 #=> 0
What the Parser Sees
Using Ruby standard libraries, you can see what the parser sees. For example:
require 'pp'
require 'ripper'
pp Ripper.sexp '1 and 0'
#=> [:program, [[:binary, [:#int, "1", [1, 0]], :and, [:#int, "0", [1, 6]]]]]
The S-expression may be a little clearer and easier to read when using the ruby_parser gem instead of Ripper. For example:
require 'pp'
require 'ruby_parser'
pp RubyParser.new.parse '1 and 0'
#=> s(:and, s(:lit, 1), s(:lit, 0))
Either way, since the first expression 1 evaluates as an Integer literal (e.g. something other than nil or false), 0 is then evaluated. The second Integer literal also evaluates as true, and therefore the entire expression is true (which is irrelevant in this context) and returns 0, since 0 was the last expression evaluated.
What You Actually Want
In Ruby, all values other than nil or false are true. Instead of the and operator, you usually want to compare expressions with an equality operator such as == or forcibly-cast an expression into a Boolean context with !!. For example:
# Evaluate equality and return a Boolean result.
1 == 1 #=> true
0 == 1 #=> false
# Evaluate whether an expression is equal to true. In this case,
# the double-negation of `!!` casts each Integer as a Boolean value.
!!1 == true #=> true
!!0 == true #=> true
# Use `and` flow-control operator to evaluate right-hand expression
# if the left-hand side evaluates as truthy.
(1) and (true) #=> true
(1) and (false) #=> false

Why does 1 === (1..12) evaluate to false, while (1..12) === 1 evaluates to true? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
=== vs. == in Ruby
I've seen it used a few times lately but can't figure out what it does. Can anyone illustrate how it works?
Just like with every other method in Ruby (or actually pretty much any object-oriented language),
a === b
means whatever the author of a's class wants it to mean.
However, if you don't want to confuse the heck out of your colleagues, the convention is that === is the case subsumption operator. Basically, it's a boolean operator which asks the question "If I have a drawer labelled a would it make sense to put b in that drawer?"
An alternative formulation is "If a described a set, would b be a member of that set?"
For example:
(1..5) === 3 # => true
(1..5) === 6 # => false
Integer === 42 # => true
Integer === 'fourtytwo' # => false
/ell/ === 'Hello' # => true
/ell/ === 'Foobar' # => false
The main usage for the === operator is in case expressions, since
case foo
when bar
baz
when quux
flurb
else
blarf
end
gets translated to something (roughly) like
_temp = foo
if bar === _temp
baz
elsif quux === _temp
flurb
else
blarf
end
Note that if you want to search for this operator, it is usually called the triple equals operator or threequals operator or case equality operator. I really dislike those names, because this operator has absolutely nothing whatsoever to do with equality.
In particular, one would expect equality to be symmetric: if a is equal to b, then b better be also equal to a. Also, one would expect equality to be transitive: if a == b and b == c, then a == c. While there is no way to actually guarantee that in a single-dispatch language like Ruby, you should at least make an effort to preserve this property (for example, by following the coerce protocol).
However, for === there is no expectation of either symmetry or transitivity. In fact, it is very much by design not symmetric. That's why I don't like calling it anything that even remotely resembles equality. It's also why I think, it should have been called something else like ~~~ or whatever.
Thanks for your edit Jacob, I was about to call you out ;) I'll post a couple of examples anyway. The implementation of === differs depending on type. For example:
(1...3) === 2
=> true
/test/ === "this is a test"
=> true
case 'test'
when /blah/
"Blach"
when /test/
"Test"
else
"Fail"
end
=> "Test"
Stephen, checkout http://ruby-doc.org/docs/ProgrammingRuby/ (the "Pickaxe"), it should be able to help you out with questions such as this in the future.
In Ruby, the === operator is used to test equality within a when clause of a case statement. In other languages, the above is true.
To my knowledge, Ruby doesn't have true operators, they are all methods which are invoked on the LHS of the expression, passing in the RHS of the expression.
So, really, you could override any "operator" you want in your classes to perform whatever the heck you want (analogous to operator overloading in C++).

3 Equals or Case Equality operator

In Ruby Integer === 5 returns true. Similarly String === "karthik" returns true.
However, 5 === Integer returns false. And "karthik" === String.
Why is the operator not commutative?
The simple answer is: because it doesn't make sense. The relationship the operator describes is not commutative, why should the operator be?
Just look at your own examples: 5 is an Integer. But is Integer a 5? What does that even mean?
=== is the case subsumption operator, and subsumption doesn't commute.
The fact that the case subsumption operator uses equals signs, and that it is usually called the triple equals, threequals or case equality operator is terribly unfortunate since it not only has absolutely nothing to do with equality, but it also does not conform to many of the laws that equality conforms to, such as transitivity and as you mentioned commutativity.
For more of my ranting about === see
What does the === operator do in Ruby?
=== vs. == in Ruby
How does Integer === 3 work?
One very simple reason is that the is_a? relationship for classes just can't be commutative. Consider the case where both operands are classes:
Class === String
This will return true because String.is_a?(Class). However String === Class will return false, because Class.is_a?(String) is false and that is of course as it should be.
Another reason is that the semantics of === depends on its left operand. This has again two reasons: a) In ruby the semantics always depend on the left operand, because the left operand is the receiver of the method call and b) it is useful, so you can use e.g. classes, ranges and regexen in a case statement with the intended semantics.
Many operators are not commutative.
The === is called the "case equality operator" because it is called when branching is a case.
It is nice and useful that:
foo = 42
case foo
when Integer
# branches here
when String
# etc...
end
It would not be very useful if
foo = Integer
case foo
when 42
# would branch here??
when 666
# etc...
end
Note that in Ruby 1.9, the === operator on a Proc/lambda will call that Proc:
divisible_by_three = ->(x){x % 3 == 0}
divisible_by_three === 42 # => true
Again, very useful in a case statement, but not much in the reverse order.
it needs to implement case-when comparisons
It's normal to have non-commutative operators.
/ - % [] . -> ^ << >> < <= > >= && || = += -= ,
And as it happens, === exists in part as the case-when operator. That's rather elaborate in Ruby, and it couldn't be so if it had to be simplified to a commutative op.

Resources