I have this stupid question about matching operator in Ruby. Why did Ruby make the matching operator =~ instead of ~=? Is there a historical, psychological or other considerations of making the former instead of the later?
I couldn't found any info on this, and I need to make sense about this because I keep typing the wrong thing due to other operator such as +=, -=, !=, >= and <= place the = on the right of the other operator, while =~ is the opposite.
Please enlight me.
My opinion is that it is more consistant. They are several 'equal' and 'match' operators. For instance:
=~ for 'matches'
!~ for 'does not match'
== for 'equals'
!= for 'does not equal'
Also from a far higher level prospective if you think about the way you would read these symbols in words it makes prefect sense:
+= -= are basically saying a = a + b or a = a - b obviously the
addition(+) or subtraction(-) must happen prior to the
assignment(=).
As for comparison operators like >= != these make sense too because
you are asking is a greater than(>) or equal to(=) bor does
a not(!) equal(=) b so why not write it that way.
In the same way ~= would be like saying does a pattern(~)
match(=) b when what you want is =~ which would read does a
match(=) pattern(~) b.
If you read them as words it become fairly succinct.
Related
I can't see a practical difference between the boolean operators AND and OR in a Ruby case conditional.
For example, I want to get the user to input the sentence:
sudo make me a sandwich
And the case conditional starts as follows:
case user_selection
when /sudo/ && /sandwich/
However, if the user enters:
make me a sandwich
The condition will be a satisfied.
My way around it in this instance is to re-order the conditions:
case user_selection
when /sandwich/ && /sudo/
But that pre-supposes that every time a user thinks to use "sudo" they will include the string "sandwich" in their response. However, this is functionally no different from this:
case user_selection
when /sudo/
I looked up boolean operators for Ruby conditionals, but have not found a satisfactory answer.
You cannot use && in a case block like that, because when /sudo/ && /sandwich/ evaluates to just when /sandwich/.
Instead you will need to use one regexp that looks for both words. A simple example might be:
case user_selection
when /sudo.*sandwich/
Just for reference.
If you absolutely need a logical AND in your case statement, you could use a lambda :
def answer(order)
case order
when ->(x) { x =~ /sudo/ && x =~ /sandwich/ }
puts 'Okay'
else
puts 'Do it yourself!'
end
end
answer 'make me a sandwich'
#=> Do it yourself!
answer 'sudo sing a song'
#=> Do it yourself!
answer 'sudo make me a sandwich'
#=> Okay
If you can compact the boolean logic to a single check (e.g. with a Regex), you probably should, as in #spickermann's answer.
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++).
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++).
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
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 ||.