Is there any wisdom behind and, or operators in Ruby?
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.
Ruby: what is the difference between the comparatives: || and or
or the second example all variables are checked and if one is true then it will execute "do something".
This is false sentence.
As a result your assumptions are not correct.
Both or
and ||
do the same thing.
The main difference is that or
has lower precedence than ||
. So you should pay attention to more complex evaluations:
# Simple cases are not confusing
false || true # true
false or true # true
# This is more complex
a = false || true # a=true
a = false or true # a=false
# Also similarly as 1 + 2*3 returns 7, the following returns true:
false or false||true # true
# BUT! THIS IS IMPORTANT!
a = false or false||true # a=false
a = (false or false||true) # a=true
Here is a list of operators precedence.
So the real difference will be noticed if you use the expression that includes any of the following operators:
.. ...
- Range (inclusive and exclusive)? :
- Ternary if-then-else= %= { /= -= += |= &= >>= <<= *= &&= ||= **=
- Assignmentdefined?
- Check if specified symbol definednot
- Logical negationand
- Logical composition
there might be others too.
You can thing about the difference between those as different between +
and *
: ||
==*
and or
=+
. The same applies to and
and not
.
You should really pay attention to that.
Personally I prefer ||
operator as its semantics is well understood and avoid or
.
While it 'feels' like or
is more friendly in many cases (see my code sample), even in trivial ones, it is a source of bugs.
Why || and or behaves differently in rails?
The reason that || and or behave differently is because of operator precedence.
Both || and && have higher precedence than the assignment operator and the assignment operator (=) has higher precedence than and/or
So your expressions will actually be evaluated as follows :-
@year = params[:year] || Time.now.year
is evaluated as
@year = ( params[:year] || Time.now.year )
and
@year = params[:year] or Time.now.year
is evaluated as
( @year = params[:year] ) or Time.now.year
If in doubt about precedence rules then use parentheses to make your meaning clear.
i = true and false in Ruby is true?
The operators &&
and and
have different precedence, and =
happens to be in between.
irb(main):006:0> i = true and false
=> false
irb(main):007:0> i
=> true
irb(main):008:0> i = true && false
=> false
irb(main):009:0> i
=> false
irb(main):010:0>
The first is read as (i = true) and false
, the second as i = (true && false)
.
Why am I seeing different results for two expressions in Ruby, one uses '&&', other uses 'and' operator?
Because they have different operator precedence.
The first evaluates as:
(print (-1 == -1)) and (myobj.nil?)
It prints true, because -1 == -1, then print returns nil and nil and false
is nil.
The second is equivalent to:
print ((-1 == -1) && (myobj.nil?))
It prints (true && false), which is false, then print returns nil.
How should I handle a conditional in Ruby where the test could result in an error?
You can just use the safe navigation operator which was introduced to Ruby in 2.3:
def author_name
author&.name
end
Note that self
is not needed in your example.
Or when you are on Ruby on Rails then you might want to use delegate
:
delegate :name, to: :author, prefix: true, allow_nil: true
Multiple LIKE and AND operators in RAILS/POSTGRESQL
PostgreSQL has a handy expr op all (array)
expression so you can say things like:
where content like all (array['%a%', '%b%', '%c'])
as a short form of:
where content like '%a%'
and content like '%b%'
and content like '%c%'
Also, ActiveRecord will conveniently replace a ?
placeholder with a comma-delimited list if you hand it a Ruby array. That lets you say things like:
Word.where('content like all (array[?])', %w[a b c].map { |c| "%#{c}%" })
and:
Word.where('content like all (array[?])', some_other_array.map { |c| "%#{c}%" })
Ruby - Loop IF x times and change condition
input = [
0,0,0,44,754,22,0,632,2,22,0,2,
nil,2,24,nil,666,90909,2,4,6,7,
2,7,3,2,2,7,1,8,6,3,2,19,5,46
]
(1..Float::INFINITY).step(4) do |i|
i = i.to_i # is float here
break Statement if i >= input.size
next if input[i].nil? || !input[i+1].zero?
keyword = Statement =~ /WHERE/ ? 'AND' : 'WHERE'
Statement.sub! "THIS", "#{keyword} #{input[i+7]} #{input[i+8]} THIS"
end
#⇒ "Statement WHERE 2 22 AND 2 AND 666 90909 THIS"
Attempt at understanding the double-dispatch pattern
In single dispatch---what you see in most modern OO languages---a method is dispatched based on the run-time type of a single object. This shows up as the dot operator (in ruby, java, javascript, etc.) or the arrow operator (perl, c++).
# look, ma single dispatch!
# method on obj's run-time type that is called
dentist.work_on(patient)
Double dispatch, then, would be based on the run-time type of two objects. There are a few ways this could look; and on which object should the method live?
# Hmm, this looks weird.
# Is the method in to dentist.class or patient.class?
(dentist, patient).do_dentistry()
# okay, this looks more familiar; the method lives on obj1.class
# This only works in static-typed languages which support double dispatch
# in which you declare the type of the method parameters.
dentist.work_on(patient)
class Dentist
def work_on(Adult patient); ...; end
def work_on(Child patient); ...; end
end
Languages like groovy that have multiple dispatch generalize the second example above; they consider the run-time types of all parameters when choosing which method to run. See for example this blog post about groovy and multiple dispatch.
Most modern OO languages only have single dispatch and the Multiple Dispatch Pattern is an attempt to get the benefits of multiple dispatch into the language. It even works for dynamic languages like ruby. It works by doing single dispatch twice in a row. The first method call will call a method on the second object.
class Dentist
def work_on(patient)
patient.dispatch_work(self)
end
def work_on_adult(patient)
drill_as_hard_as_you_can(patient)
end
def work_on_child(patient)
use_bubble_gum_toothpaste(patient)
give_toothbrush_to(patient)
end
end
class Doctor
def work_on(patient)
patient.dispatch_work(self)
end
def work_on_adult(patient)
do_checkup(patient)
end
def work_on_child(patient)
assure_presence_of(patient.guardian)
ask_questions_to(patient.guardian)
do_checkup(patient)
give_cheap_toy_to(patient)
end
end
class Adult
def dispatch_work(dentist)
dentist.work_on_adult(self)
end
end
class Child
def dispatch_work(dentist)
dentist.work_on_child(self)
end
end
The double dispatch pattern is what I call a low-level pattern because other patterns are built on it. For example, the Visitor pattern relies heavily on the double dispatch pattern.
Update Just saw your gists. Your first gist isn't really doing double dispatch. Sure, you're dispatching twice, but you're not changing the behavior in that second dispatch. To change it to double dispatch I'd do something like this.
class Chicken
def make_dispatch dish
dish.make_with_chicken self
end
end
class Beef
def make_dispatch dish
dish.make_with_beef self
end
end
module Dish
def make meat
meat.make_dispatch self
end
end
class Sandwich
include Dish
def make_with_chicken chicken
puts "Grilled Chicken Sandwich"
end
def make_with_beef beef
puts "Roast Beef Sandwich"
end
end
class Stew
include Dish
def make_with_chicken chicken
puts "Thai curry"
end
def make_with_beef beef
puts "Beef stew"
end
end
class Casserole
include Dish
def make_with_chicken chicken
puts "Chicken Pot Pie--or something"
end
def make_with_beef beef
puts "Shepard's Pie"
end
end
Sandwich.new.make(Chicken.new)
Stew.new.make(Chicken.new)
Casserole.new.make(Beef.new)
Related Topics
Using Rails Serialize to Save Hash to Database
How to Determine If One Array Contains All Elements of Another Array
Test If String Is a Number in Ruby on Rails
Require': Cannot Load Such File - 'Nokogiri\Nokogiri' (Loaderror) When Running 'Rails Server'
Gem Installation Error: You Have to Install Development Tools First (Windows)
Best Way to Escape and Unescape Strings in Ruby
Reducing N+1 Queries Using the Bullet and Rspec Gems
What Does @@Variable Mean in Ruby
Rails Keeps Telling Me That It's Not Currently Installed
Rhc Setup Gives Error 'No Such File Dl/Import'
How to Get a Specific Output Iterating a Hash in Ruby
Double Colons Before Class Names in Ruby
What Do 'I' and '-I' in Regex Mean
Heroku - Cannot Run Git Push Heroku Master
Sort an Array According to the Elements of Another Array