

Good Ruby Idiom: and/or operators
source link: https://zverok.github.io/blog/2016-02-23-control-flow.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Good Ruby Idiom: and/or operators
Feb 23, 2016
Any tutorial and book will teach you there are two sets of similar
operators in Ruby: &&
/||
vs and
/or
(and also &
/|
for bit
operations, but that’s not the case today). But typical tutorial will not
provide further explanation why we need both of those pairs.
Some of tutorials and blog posts about this matter even go as far as
explicit recommendations never use and
/or
, because &&
and ||
is enough for all reasonable cases, and because and
/or
provide only
confusion. They would typically warn
you about and
’s lower precedence than =
, but nobody will tell you
how this can and should be useful.
Unfortunately, even respectable (and forced by Rubocop)
Ruby Style Guide explicitly
bans those
operators and embraces usage of &&
and ||
even for control flow.
(Faithfully, this is one of Rubocop checks I turn off immediately after
adding Rubocop to every new project of mine.)
But and
and or
are you friends, which allow to write very clean and
DRY and readable code: exactly the thing we love Ruby for.
They are control flow operators.
Example:
File.exists? or raise "No config file!"
document.ready? and return
This idiom is one of (numerous) good parts of Perl heritage in Ruby, it is very terse and readable and demonstrate intentions well.
Somebody may argue &&
and ||
can be used for both examples? Or, to
heck with it, why we should do control flow this way, we have our if
and unless
, even modyfying ones?..
So, let’s look at some examples.
Case 1. Task: receive some data from method; if data received, process it further, if not—return (or fail) immediately. For example, complex Nokogiri document parsing:
def extract_actors(movie_doc)
list = movie_doc.at('ul#actorsList')
# now, if no list in doc, we should return, otherwise do lots of stuff
What options do we have?
# option 1
list = movie_doc.at('ul#actorsList')
return unless list # extra independent statement
# option 2
if (list = movie_doc.at('ul#actorsList'))
# ^ extra parentheses for distinguishing from ==
end
# option 3..20
# ...your choice!
# using control flow operator:
list = movie_doc.at('ul#actorsList') or return
Which is cleaner declaration of intent?.. For me—definitely the last one.
And you can’t replace it with ||
, exactly because of operator precedence.
Case 2. List of checks: before some complex processing you want to check your arguments and maybe state, fail if something is not OK, and only then do the processing.
I do it like this:
File.exists?(config) or raise "Configuration file #{config} not found"
x.is_a?(Numeric) && y.is_a?(Numeric) or
raise "Only numeric values expected"
halted? || waits_for_halt? and raise "Process already halted"
# ...now to your normal processing code...
The same code with modyfying if/unless is not that clear:
raise "Configuration file #{config} not found" unless File.exists?(config)
raise "Only numeric values expected" unless x.is_a?(Numeric) && y.is_a?(Numeric)
raise "Process already halted" if halted? || waits_for_halt?
Code with control flow operators reads like
IMPORTANT_CONDITION or raise ...something...
. Code with modifying statements
reads like raise THIS LONG VALUEABLE STRING unless .... something
.
And again, you will not want to use &&
and ||
here because of operator
precedence (and some complications with parentheses, also).
I like this (a bit abstruse) definition:
Logical operators (
&&
and||
) operate on values; control flow operators (and
andor
) operate on side effects.
PS: Of course, this is not first blog post with such kind of rant/explanation, there are plenty of them. Just wanted to make [another] clear point about that.
Recommend
-
21
The pImpl idiom is a useful idiom in C++ to reduce compile-time dependencies. Here is a quick overview of what to keep in mind when we implement and use it. What is it? The pImpl...
-
20
This post is part of Advent of Parens 2019 , my attempt to publish one blog post a day during the 24 days of the advent. Here’s a little Cl...
-
11
Execute Around idiom in Java The Execute Around idiom is a pattern that allows you to wrap an action with some standard setup / tear down s...
-
7
Parallel assignment: a Python idiom cleverly optimized Friday, May 15, 2020 Every programmer has had to swap variables. It's common in real programs and it's a frequently used example when...
-
9
an alternative to Pimpl The C++ Priv idiom: an alternative to Pimpl by Yair Chuchem 2021.03.09 C++ is infamous for long compilatio...
-
8
Please repeat yourself: The noexcept(noexcept(…)) idiom Raymond C April 8th, 2022 Consider the following class:...
-
6
The copy and swap idiom in C++ Sandor Dargo 21 hours ago2022-08-10T00:00:00+02:00Last year, as the usage of our services grew sometimes by 20 times, we had to spend significant efforts on optimizing our appl...
-
7
The Template Method Pattern and the Non-Virtual Idiom Sandor Dargo 3 days ago2022-08-24T00:00:00+02:00The above title is also one of the chapter titles from
-
7
Ranked #13 for todayIdiomicsIdiom illustrations for brands and bloggersPayment RequiredIdiomics i...
-
6
Erase-Remove Idiom in C++Skip to content
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK