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
What is the name of the method corresponding to the ternary operator? By name I mean :+ for addition, :== for equality, etc.
I want to override the ternary operator to build a proxy class (same idea as Javascript proxies) but I can't seem to find the name for this.
There are two names that this is known by, if you are talking about the ? : operator, and that is ternary operator or conditional operator.
But it is not a method, as you can see in this table.
You would need to go to Ruby Source itself to override the behavior. Probably not what you would want to do.
I'm pretty sure it's just known as the ternary operator. Usually people know what you mean when you say that, and I've never heard or seen another name, even during research.
If you mean symbol, I'd call it:
?:
(Question mark, Colon)
I am trying to detect if the email address is not one of two domains but I am having some trouble with the ruby syntax. I currently have this:
if ( !email_address.end_with?("#domain1.com") or !email_address.end_with?("#domain2.com"))
#Do Something
end
Is this the right syntax for the conditions?
Rather than an or here, you want a logical && (and) because you are trying to find strings which match neither.
if ( !email_address.end_with?("#domain1.com") && !email_address.end_with?("#domain2.com"))
#Do Something
end
By using or, if either condition is true, the whole condition will still be false.
Note that I am using && instead of and, since it has a higher precedence. Details are well outlined here
From the comments:
You can build an equivalent condition using unless with the logical or ||
unless email_address.end_with?("#domain1.com") || email_address.end_with?("#domain2.com")
This may be a bit easier to read since both sides of the || don't have to be negated with !.
If more domains are added, then the repetitive email_address.end_with? is getting boring real fast. Alternative:
if ["#domain1.com", "#domain2.com"].none?{|domain| email_address.end_with?(domain)}
#do something
end
I forgot end_with? takes multiple arguments:
unless email_address.end_with?("#domain1.com", "#domain2.com")
#do something
end
How about:
(!email_address[/#domain[12]\.com\z/])
array.include? 'foo' or array.include? 'bar'
is a syntax error (unexpected keyword_or). Parentheses solve the problem, but as I'm new to Ruby I've no idea which of the following is considered more idiomatic:
Option 1
array.include?('foo') or array.include?('bar')
Option 2
(array.include? 'foo') or (array.include? 'bar')
Does this come down to personal preference, or is one approach considered more "correct"?
I'd suggest you take a look at the community-driven Ruby coding style guide, here particularly the section on Syntax.
Omit parentheses around parameters for methods that are part of an internal DSL (e.g. Rake, Rails, RSpec), methods that are with "keyword" status in Ruby (e.g. attr_reader, puts) and attribute access methods. Use parentheses around the arguments of all other method invocations. - excerpt from the guide
class Person
attr_reader :name, :age
# omitted
end
temperance = Person.new('Temperance', 30)
temperance.name
puts temperance.age
x = Math.sin(y)
array.delete(e)
Are you sure that is failing? Your initial example works fine for me.
ruby-1.9.2-p290 :002 > array = ['bar']
=> ["bar"]
ruby-1.9.2-p290 :003 > array.include? 'foo' or array.include? 'bar'
=> true
As a matter of fact, if anything could be considered idiomatic it would be that one. The low precedence of or allows this to work when you leave the parens off. This characteristic is something that should make it idiomatic to Ruby (and even Perl, which or is a hold over from).
Option 1 is super clear, but considering you included the parens you really have no need to use or. It's probably better to use ||, which has a high precedence like other operators and is just more common. I think using or for the sake of it looking like english is not a great practice. It has a semantic meaning within the language and is probably best used for those qualities.
Option 2 is silly of course. If you're going to include parens, you might as well use them for the method signature.
Hope this helps.
Avdi Grimm reckons you shouldn't use and or or for boolean logic. You should only and or or for control flow (analogous to if or unless)
According to his recommendation, you should use || instead:
array.include?('foo') || array.include?('bar')
Option 1 is preferred since it's common to other languages as well. Option 2 looks like LISP, which is not popular nowadays.
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.
I just came across this idiom in some open-source Python, and I choked on my drink.
Rather than:
if isUp:
return "Up"
else:
return "Down"
or even:
return "Up" if isUp else "Down"
the code read:
return isUp and "Up" or "Down"
I can see this is the same result, but is this a typical idiom in Python? If so, is it some performance hack that runs fast? Or is it just a once-off that needs a code review?
The "a and b or c" idiom was the canonical way to express the ternary arithmetic if in Python, before PEP 308 was written and implemented. This idiom fails the "b" answer is false itself; to support the general case, you could write
return (a and [b] or [c])[0]
An alternative way of spelling it was
return (b,c)[not a]
which, with the introduction of the bool type, could be rewritten as
return (c,b)[bool(a)]
(in case it isn't clear: the conversion to bool, and the not operator, is necessary if a is not known to be bool already)
Today, the conditional expression syntax should be used if the thing must be an expression; else I recommend to use the if statement.
You should read Using the and-or trick (section 4.6.1) of Dive Into Python by Mark Pilgrim. It turns out that the and-or trick has major pitfalls you should be aware of.
That code is a big fugly and clever for my tastes, but I suppose there's not anything wrong with it per se. I think this is really just a case of "make it all fit in one line" syndrome.
I personally would have opted for the first form though.
Yikes. Not readable at all. For me pythonic means easy to read.
return isUp and "Up" or "Down"
Sounds something you would do in perl.
No, it is not.
I had a somehow similar question the other day.
if the construct
val if cond else alt
Was not very welcome ( at least by the SO community ) and the preferred one was:
if cond:
val
else:
alt
You can get your own conclusion. :)