I wonder why ruby give and, or less precedence than &&, || , and assign operator? Is there any reason?
My guess is that's a direct carry-over from Perl. The operators or and and were added later in Perl 5 for specific situations were lower precedence was desired.
For example, in Perl, here we wish that || had lower precedence, so that we could write:
try to perform big long hairy complicated action || die ;
and be sure that the || was not going to gobble up part of the action. Perl 5 introduced or, a new version of || that has low precedence, for exactly this purpose.
An example in Ruby where you could use or but not ||:
value = possibly_false or raise "foo"
If you used ||, it would be a syntax error.
The difference is precedence. ||, && have higher precedence than =, but and, or have lower. So while you can do:
a = nil || 0
You would have to do:
a = (nil or 0)
to get same effect. If you do:
a = nil or 0
The result of expression would still be 0, but a value would be nil.
They have very low precedence so that the operands don't have to be wrapped in parentheses, as is sometimes the case with && and ||.
Being able to control the precedence of your operators is sometimes useful, especially if you are concerned with readability -- extra parenthesis in conditional statements can sometimes obscure the actual logic.
To be frank, though, I think the reason Ruby has the boolean operator precedence levels it does stems mostly from the fact that Matz was a Perl programmer before he ever wrote Ruby, and borrowed much of the core syntax and operators from that language.
I believe the idea is specifically to get them below the assignment operators, so you can write logic tests with assignments but without parens.
Related
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 ||.
new to TCL and running into a short circuit issue it seems. Coming from vbscript, I'm able to perform this properly, but trying to convert to a TCL script I'm having issues with the short circuit side effect and have been trying to find the proper way of doing this.
In the following snippet, I want to execute "do something" only if BOTH sides are true, but because of short circuiting, it will only evaluate the second argument if the first fails to determine the value of the expression.
if {$basehour != 23 && $hours != 0} {
do something
}
Maybe I'm not searching for the right things, but so far I've been unable to find the solution. Any tips would be appreciated.
The && operator always does short-circuiting in Tcl (as it does in C and Java and a number of other languages too). If you want the other version and can guarantee that both sub-expressions yield booleans (e.g., they come from equality tests such as you're doing) then you can use the & operator instead, which does bit-wise AND and will do what you want when working on bools. If you're doing this, it's wise to put parentheses around the sub-expressions for clarity; while everyone remember the precedence of == with respect to &&, the order w.r.t. & is often forgotten. (The parentheses are free in terms of execution cost.)
if {($basehour != 23) & ($hours != 0)} {
do something
}
However, it's usually not necessary to do this. If you're wanting an AND that you're feeding into a boolean test (e.g., the if command's expression) then there's no reason to not short-circuit, as in your original code; if the first clause gives false, the second one won't change what value the overall expression produces.
The case/when statements remind me of try/catch statements in Python, which are fairly expensive operations. Is this similar with the Ruby case/when statements? What advantages do they have, other than perhaps being more concise, to if/elsif Ruby statements? When would I use one over the other?
The case expression is not at all like a try/catch block. The Ruby equivalents to try and catch are begin and rescue.
In general, the case expression is used when you want to test one value for several conditions. For example:
case x
when String
"You passed a string but X is supposed to be a number. What were you thinking?"
when 0
"X is zero"
when 1..5
"X is between 1 and 5"
else
"X isn't a number we're interested in"
end
The case expression is orthogonal to the switch statement that exists in many other languages (e.g. C, Java, JavaScript), though Python doesn't include any such thing. The main difference with case is that it is an expression rather than a statement (so it yields a value) and it uses the === operator for equality, which allows us to express interesting things like "Is this value a String? Is it 0? Is it in the range 1..5?"
Ruby's begin/rescue/end is more similar to Python's try/catch (assuming Python's try/catch is similar to Javascript, Java, etc.). In both of the above the code runs, catches errors and continues.
case/when is like C's switch and ignoring the === operator that bjhaid mentions operates very much like if/elseif/end. Which you use is up to you, but there are some advantages to using case when the number of conditionals gets long. No one likes /if/elsif/elsif/elsif/elsif/elsif/end :-)
Ruby has some other magical things involving that === operator that can make case nice, but I'll leave that to the documentation which explains it better than I can.
I understand the difference between them, but I can't work out why they're both included in the language. Surely having both just causes confusion?
Their precedence is different, so they are not equivalent.
My rule of thumb is as follows: use && for logical expressions and use and for control flow.
Examples
# logical expressions
if user.first_name == 'Bob' && user.last_name == 'Jones'
# control flow
worker.do_this and worker.and_also_do_this_if_that_went_well
Perl has the same doublets, even with the same precedence difference as in Ruby.
Ruby was strongly influenced by Perl.
I believe one should look no further.
Do go through this:
http://phrogz.net/ProgrammingRuby/language.html#andornotanddefined
This is the best explanation I've seen:
http://avdi.org/devblog/2010/08/02/using-and-and-or-in-ruby/
Related Questions: Benefits of using short-circuit evaluation, Why would a language NOT use Short-circuit evaluation?, Can someone explain this line of code please? (Logic & Assignment operators)
There are questions about the benefits of a language using short-circuit code, but I'm wondering what are the benefits for a programmer? Is it just that it can make code a little more concise? Or are there performance reasons?
I'm not asking about situations where two entities need to be evaluated anyway, for example:
if($user->auth() AND $model->valid()){
$model->save();
}
To me the reasoning there is clear - since both need to be true, you can skip the more costly model validation if the user can't save the data.
This also has a (to me) obvious purpose:
if(is_string($userid) AND strlen($userid) > 10){
//do something
};
Because it wouldn't be wise to call strlen() with a non-string value.
What I'm wondering about is the use of short-circuit code when it doesn't effect any other statements. For example, from the Zend Application default index page:
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
This could have been:
if(!defined('APPLICATION_PATH')){
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
}
Or even as a single statement:
if(!defined('APPLICATION_PATH'))
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
So why use the short-circuit code? Just for the 'coolness' factor of using logic operators in place of control structures? To consolidate nested if statements? Because it's faster?
For programmers, the benefit of a less verbose syntax over another more verbose syntax can be:
less to type, therefore higher coding efficiency
less to read, therefore better maintainability.
Now I'm only talking about when the less verbose syntax is not tricky or clever in any way, just the same recognized way of doing, but in fewer characters.
It's often when you see specific constructs in one language that you wish the language you use could have, but didn't even necessarily realize it before. Some examples off the top of my head:
anonymous inner classes in Java instead of passing a pointer to a function (way more lines of code).
in Ruby, the ||= operator, to evaluate an expression and assign to it if it evaluates to false or is null. Sure, you can achieve the same thing by 3 lines of code, but why?
and many more...
Use it to confuse people!
I don't know PHP and I've never seen short-circuiting used outside an if or while condition in the C family of languages, but in Perl it's very idiomatic to say:
open my $filehandle, '<', 'filename' or die "Couldn't open file: $!";
One advantage of having it all in one statement is the variable declaration. Otherwise you'd have to say:
my $filehandle;
unless (open $filehandle, '<', 'filename') {
die "Couldn't open file: $!";
}
Hard to claim the second one is cleaner in that case. And it'd be wordier still in a language that doesn't have unless
I think your example is for the coolness factor. There's no reason to write code like that.
EDIT: I have no problem with doing it for idiomatic reasons. If everyone else who uses a language uses short-circuit evaluation to make statement-like entities that everyone understands, then you should too. However, my experience is that code of that sort is rarely written in C-family languages; proper form is just to use the "if" statement as normal, which separates the conditional (which presumably has no side effects) from the function call that the conditional controls (which presumably has many side effects).
Short circuit operators can be useful in two important circumstances which haven't yet been mentioned:
Case 1. Suppose you had a pointer which may or may not be NULL and you wanted to check that it wasn't NULL, and that the thing it pointed to wasn't 0. However, you must not dereference the pointer if it's NULL. Without short-circuit operators, you would have to do this:
if (a != NULL) {
if (*a != 0) {
⋮
}
}
However, short-circuit operators allow you to write this more compactly:
if (a != NULL && *a != 0) {
⋮
}
in the certain knowledge that *a will not be evaluated if a is NULL.
Case 2. If you want to set a variable to a non-false value returned from one of a series of functions, you can simply do:
my $file = $user_filename ||
find_file_in_user_path() ||
find_file_in_system_path() ||
$default_filename;
This sets the value of $file to $user_filename if it's present, or the result of find_file_in_user_path(), if it's true, or … so on. This is seen perhaps more often in Perl than C, but I have seen it in C.
There are other uses, including the rather contrived examples which you cite above. But they are a useful tool, and one which I have missed when programming in less complex languages.
Related to what Dan said, I'd think it all depends on the conventions of each programming language. I can't see any difference, so do whatever is idiomatic in each programming language. One thing that could make a difference that comes to mind is if you had to do a series of checks, in that case the short-circuiting style would be much clearer than the alternative if style.
What if you had a expensive to call (performance wise) function that returned a boolean on the right hand side that you only wanted called if another condition was true (or false)? In this case Short circuiting saves you many CPU cycles. It does make the code more concise because of fewer nested if statements. So, for all the reasons you listed at the end of your question.
The truth is actually performance. Short circuiting is used in compilers to eliminate dead code saving on file size and execution speed. At run-time short-circuiting does not execute the remaining clause in the logical expression if their outcome does not affect the answer, speeding up the evaluation of the formula. I am struggling to remember an example. e.g
a AND b AND c
There are two terms in this formula evaluated left to right.
if a AND b evaluates to FALSE then the next expression AND c can either be FALSE AND TRUE or FALSE AND FALSE. Both evaluate to FALSE no matter what the value of c is. Therefore the compiler does not include AND c in the compiled format hence short-circuiting the code.
To answer the question there are special cases when the compiler cannot determine whether the logical expression has a constant output and hence would not short-circuit the code.
Think of it this way, if you have a statement like
if( A AND B )
chances are if A returns FALSE you'll only ever want to evaluate B in rare special cases. For this reason NOT using short ciruit evaluation is confusing.
Short circuit evaluation also makes your code more readable by preventing another bracketed indentation and brackets have a tendency to add up.