Does ruby need ternary operator at all? - ruby

I made a small test today:
> false && 1 || 2
> 2
> true && 1 || 2
> 1
So if we could already do with binary operators, why did we need a ternary ?
> false ? 1 : 2
> 2
> true ? 1 : 2
> 1
As it is not simply an alias and complicates parsing.

To deal with the specific case in your question…
What if 1 was different value, one that evaluated as false?
And in general:
No. You can always replace a ternary operator with an if/else construct. That isn't as convenient though.

No language needs a ternary operator.
The ternary operator is a well-known language construct. IMO people generally expect it in script-ish(-looking) languages, so there it is. I don't see a huge reason to not have it.

The conditional operator is needed in languages like C, because if/else is a statement, it doesn't evaluate to a return value. But in Ruby, everything is an expression, everything has a return value, there are no statements.
Therefore, you can always replace the conditional operator with a conditional expression:
foo = bar ? baz : qux
is exactly equivalent to
foo = if bar then baz else qux end
In C, you cannot write this, you'd have to write
if bar then foo = baz else foo = aux end
leading to code duplication. That's why you need the conditional operator in C. In Ruby, it is unnecessary.
Actually, since Ruby is an object-oriented language, all conditionals are unnecessary. You can just use polymorphism instead.

Related

Ruby `&&` vs `and` in a block [duplicate]

This question already has answers here:
Difference between "and" and && in Ruby?
(8 answers)
Closed 6 years ago.
In the code below, if I replace the and in the any? statement with &&, it throws an error unexpected tIDENTIFIER, expecting '}'.
def ArrayAddition(arr)
i = 2
until i == arr.length
combinations = arr.permutation(i).to_a
return true if combinations.any?{|array| array.inject(&:+) == arr.max and !array.include? arr.max}
i+=1
end
false
end
What is going on here? Does Ruby handle these operators differently?
The operators and and && have different precedence, and are not equivalent. As such, the Ruby Style Guide advises against using and and or operators: The and and or keywords are banned. It's just not worth it. Always use && and || instead.
Due to the difference in precedence, the other operators in the expression have higher or lower comparative precedence. In this case, the argument for the Array#include? call end up binding to the wrong expression.
You can solve this by adding parentheses around the argument to the Array#include? call.
Yes. and has lower precedence than && (and almost everything else). This expression:
foo and bar baz
...is parsed like this:
foo and (bar baz)
...so Ruby knows foo is a method name (because it can't be anything else). On the other hand, this expression:
foo && bar baz
...is parsed like this:
(foo && bar) baz
...which just doesn't make sense and you get a syntax error.
Generally speaking you should use && unless you specifically want and's lower precedence, so in this case the easiest fix to the syntax error is to use parentheses around the method argument:
foo && bar(baz)
...and so:
array.inject(&:+) == arr.max && !array.include?(arr.max)
As a bonus, this is more readable as well.

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

What does the "===" operator do in Ruby? [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++).

Ruby ternary operator without else

Is there a ruby idiom for "If do-this," and "do-this" just as a simple command?
for example, I'm currently doing
object.method ? a.action : nil
to leave the else clause empty, but I feel like there's probably a more idiomatic way of doing this that doesn't involve having to specify a nil at the end. (and alternatively, I feel like taking up multiple lines of code would be wasteful in this case.
As a general rule: you pretty much never need the ternary operator in Ruby. The reason why you need it in C, is because in C if is a statement, so if you want to return a value you have to use the ternary operator, which is an expression.
In Ruby, everything is an expression, there are no statements, which makes the ternary operator pretty much superfluous. You can always replace
cond ? then_branch : else_branch
with
if cond then then_branch else else_branch end
So, in your example:
object.method ? a.action : nil
is equivalent to
if object.method then a.action end
which as #Greg Campbell points out is in turn equivalent to the trailing if modifier form
a.action if object.method
Also, since the boolean operators in Ruby not just return true or false, but the value of the last evaluated expression, you can use them for control flow. This is an idiom imported from Perl, and would look like this:
object.method and a.action
a.action if object.method?
Greg's answer is the best, but for the record, and even more than in C, expressions and statements are equivalent in Ruby, so besides a.action if o.m? you can also do things like:
object.method? && a.action
You can write (a; b; c) if d or even
(a
b
c
) if d
or for that matter: (x; y; z) ? (a; b c) : (d; e; f)
There is no situation in Ruby where only a single statement or expression is allowed...
result = (<expression> && <true value>) || <false value>
value = 1
result = (value == 1 && 'one' ) || 'two'
result #=> 'one'
Explain: value == 1 && 'one' #=> returns last expression result, value is equals 1 so and section will be evaluated, and return 'one'.
value = 0
result = (value == 1 && 'one' ) || 'two'
result #=> 'two'
Explain: value != 1 and 'and' expression will not be evaluated, but instad will be used 'or' expression and it returns 'two'
Another way this can be done on the same line is:
if object.method; a.action end
This is considered bad style by Rubocop because it uses a semicolon to terminate the expression, but I find it more readable in some conditions than tacking on the if statement at the end. It is easier to overlook an if statement at the end and I don't always want to return something if the condition isn't true(as you are forced into with a ternary operator).
You can also be a bit more verbose and rubocop friendly:
if object.method then a.action end

Difference between "or" and || in Ruby? [duplicate]

This question already has answers here:
Difference between "and" and && in Ruby?
(8 answers)
Closed 3 years ago.
What's the difference between the or and || operators in Ruby? Or is it just preference?
It's a matter of operator precedence.
|| has a higher precedence than or.
So, in between the two you have other operators including ternary (? :) and assignment (=) so which one you choose can affect the outcome of statements.
Here's a ruby operator precedence table.
See this question for another example using and/&&.
Also, be aware of some nasty things that could happen:
a = false || true #=> true
a #=> true
a = false or true #=> true
a #=> false
Both of the previous two statements evaluate to true, but the second sets a to false since = precedence is lower than || but higher than or.
As the others have already explained, the only difference is the precedence. However, I would like to point out that there are actually two differences between the two:
and, or and not have much lower precedence than &&, || and !
and and or have the same precedence, while && has higher precedence than ||
In general, it is good style to avoid the use of and, or and not and use &&, || and ! instead. (The Rails core developers, for example, reject patches which use the keyword forms instead of the operator forms.)
The reason why they exist at all, is not for boolean formulae but for control flow. They made their way into Ruby via Perl's well-known do_this or do_that idiom, where do_this returns false or nil if there is an error and only then is do_that executed instead. (Analogous, there is also the do_this and then_do_that idiom.)
Examples:
download_file_via_fast_connection or download_via_slow_connection
download_latest_currency_rates and store_them_in_the_cache
Sometimes, this can make control flow a little bit more fluent than using if or unless.
It's easy to see why in this case the operators have the "wrong" (i.e. identical) precedence: they never show up together in the same expression anyway. And when they do show up together, you generally want them to be evaluated simply left-to-right.
and/or are for control flow.
Ruby will not allow this as valid syntax:
false || raise "Error"
However this is valid:
false or raise "Error"
You can make the first work, with () but using or is the correct method.
false || (raise "Error")
puts false or true --> prints: false
puts false || true --> prints: true
The way I use these operators:
||, && are for boolean logic. or, and are for control flow. E.g.
do_smth if may_be || may_be -- we evaluate the condition here
do_smth or do_smth_else -- we define the workflow, which is equivalent to
do_smth_else unless do_smth
to give a simple example:
> puts "a" && "b"
b
> puts 'a' and 'b'
a
A well-known idiom in Rails is render and return. It's a shortcut for saying return if render, while render && return won't work. See "Avoiding Double Render Errors" in the Rails documentation for more information.
or is NOT the same as ||. Use only || operator instead of the or operator.
Here are some reasons. The:
or operator has a lower precedence than ||.
or has a lower precedence than the = assignment operator.
and and or have the same precedence, while && has a higher precedence than ||.
Both or and || evaluate to true if either operand is true. They evaluate their second operand only if the first is false.
As with and, the only difference between or and || is their precedence.
Just to make life interesting, and and or have the same precedence, while && has a higher precedence than ||.
Just to add to mopoke's answer, it's also a matter of semantics. or is considered to be a good practice because it reads much better than ||.

Resources