Negating expressions - ruby

Is there any difference between these two statements:
! (name == "bob")
and
name != "bob"
To me, it seems like they both do the same thing. How are they different, if at all?

They are almost the same.
! (name == "bob") calls two methods ! and ==. you can write it like name.==('bob').!.
name != "bob" calls only one method !=. name.!=('bob').
Unless you redefine !=, you don't have to worry about these two options. In most cases, they are the same.
Here is an example how you can break it:
name = 'bob'
def name.!= s
true
end
name.!=('bob') # => true
name.==('bob').! # => false
You may expect the first result to be false because the 'bob' on the left side (variable name) equals 'bob' on the right side, but it does not because the method is redefined.

Those would return the same result in any example I could think of, but placing the ! before the expression can be helpful when checking other things (e.g. !my_array.include?("bob").

Related

Using || in arguments in Ruby?

I just saw this code:
method_name(ARGV.shift || "somefile.txt")
which basically should first evalute ARGV[0] and if it doesn't exist then read from "somefile.txt".
My question was, can the && operator be also used here, and in what situations?
Also, does this concept of "passing this or this argument" to a method in Ruby have a name?
The short answer, logical operators are going to return one of its operands based on if it's truthy or falsey. In practice, nearly everything in Ruby will evaluate to true except false or nil.
Examples:
expr1 || expr2 will return (expr1 if not falsey) or (expr2)
In other words, the first truthy value or the final operand,
expr1 && expr2 will return (expr1 if falsey) or (expr2).
In other words, the first falsey value or the final operand.
As for an actual use case, a similar example would be:
Using the && operator to check for a flag in ARGV then passing the file name.
method_name(ARGV.include?('-w') && "write_file.txt")
It should be noted that this is probably not a widely accepted practice. (see comments)
However, preferring a user supplied value over a default value, by using ||, in this manner would be.
If && is used, then the argument would be nil when there is no ARGV[0] and "somefile.txt" when there is ARGV[0]. Note that elements of ARGV, if any, would be strings, so there is no possibility of ARGV[0] being nil or false when there is an element passed.
Generally, || and && are called "(short circuit) disjunction" and "(short circuit) conjunction", respectively.
A typical use case of || is to provide a default value:
foo = potentially_falesy_value || default
A typical use case of && is to provide a value that depends on the truthness of another value:
foo = hash[:bar] && hash[:bar][:baz]
|| is using for providing default values. || returns first "true" value. "True" value -- value that is interpreted as true boolean value in ruby. So first "true" value in the chain will be as the result of the expression. && returns first "false" value. Complete analogy. But it does not have such graceful application.
Apart from the obvious Boolean operator functionality, && can be used like you could in some languages such as JavaScript:
a = cond1 && cond2 && value # a is now value if cond1 and cond2,
# else nil or false (depends on cond1 and cond2)
It's not very readable (IMHO) when assigning non-Boolean variables, but it works.
first evalute ARGV[0] and if it doesn't exist then read from "somefile.txt". My ques
You are correct. The ARGV.shift || "somefile.txt" expression will evaluate to ARGV.shift if it returns some non-falsy value, and "somefile.txt" otherwise. Some other examples:
puts nil || "foo" # => "foo"
puts "foo" || "bar" # => "foo"
puts "foo" || nil # => "foo"
puts "foo" || raise # => "foo"
# and doesn't blow up, because the 'raise'
# is never evaluated
can the && operator be also used here
Sure, but is arguably of less practical value. It might be clearer to use an if in that case:
puts foo && bar
# is the same as:
if foo
puts bar
end
# or:
puts bar if foo
does this concept of "passing this or this argument to a method in Ruby" has a name?
I'm not sure if it has any 'official' name, but I commonly see this pattern being called 'default value' or 'fallback value'.

Using ! on a method in Ruby

I am currently using capitalize!:
user_input.capitalize!
But, if the input is capitalized, it returns a nil.
I know I can use the method without !, but it will make a copy of the object and pass that instead of changing the object.
user_input.capitalize
How can I use !, but have it work for all cases?
I tried to downcase everything, then capitalize but the same problem exists in some cases.
What is the best way to capitalize all entries?
This is the context:
The user inputs "works", "Works", "WORKS", or "WoRkS"
case 1) user_input = "works"
case 2) user_input = "Works"
case 3) user_input = "WORKS"
case 4) user_input = "WoRkS"
user_input.capitalize! (case 1,3,4 = "Works"; case 2 = nil)
! methods, by convention, modify the receiver and return nil if they make no changes. The safest way to do it is to use two lines:
user_name.capitalize!
user_name
or #tap:
user_name.tap do |s|
s.capitalize!
end
Although, #tap is overkill here.
If all you care about is that the input gets capitalized, use capitalize! and don't worry about the nil.
If you can't have a nil at a certain point in your code (for some reason), don't use capitalize!. Instead do this:
user_input = user_input.capitalize
At the end of the day, either way is fine, idiomatic and will get the input into the state you want it. In and of itself, a nil return value isn't a bad thing - although you may not always want it as a final return value.

Why can procs be invoked with === in ruby 1.9?

This article mentions 4 ways to invoke procs in ruby 1.9, and === is one of them. I don't understand why this would be done this way at all. Does it have any relationship to the normal meaning of === (asking if the two objects are the same object)?
irb(main):010:0> f =-> n {[:hello, n]}
=> #
irb(main):011:0> f.call(:hello)
=> [:hello, :hello]
irb(main):012:0> f === :hello
=> [:hello, :hello]
irb(main):013:0> Object.new === Object.new
=> false
irb(main):014:0> f === f
=> [:hello, #]
Note that === in Ruby is NOT about equality, unlike JavaScript. It is specifically used for case expressions:
case cats.length
when 42 # Uses 42 === cats.length
puts :uh
when /cool/i # Uses /cool/i === cats.length
puts :oh
when ->(n){ n.odd? || n/3==6 } # Passes cats.length to the proc
puts :my
end
This is what the docs have to say:
It is to allow a proc object to be a target of when clause in the
case statement.
This is a, perhaps contrived, example:
even = proc { |x| x % 2 == 0 }
n = 3
case n
when even
puts "even!"
else
puts "odd!"
end
It works because the case/when is basically executed like this:
if even === n
puts "even!"
else
puts "odd!"
end
The case/when checks which branch to execute by calling === on the arguments to when clauses, picking the first that returns a truthy value.
Despite its similarity to the equality operator (==) it not a stronger or weaker form of it. I try to think of the === operator as the "belongs to" operator. Class defines it so that you can check if an object belongs to the class (i.e. is an instance of the class or a subclass of the class), Range defines it as to check if the argument belongs to the range (i.e. is included in the range), and so on. This doesn't really make the Proc case make more sense, but think of it as a tool for making your own belongs to operators, like my example above; I defined an object that can determine if something belongs to the set of even numbers.
This feature is useful in case construction, when you need to calculate something at the comparing.
is_odd =-> n { n%2 != 0 }
is_even =-> n { n%2 == 0 }
case 5
when is_even
puts "the number is even"
when is_odd
puts "the number is odd"
end
=> the number is odd
Does it have any relationship to the normal meaning of === (asking if the two objects are the same object)?
Actually, that's a common misconception about === in Ruby. It's actually not strictly for Object#object_id comparison (although that is its behavior in many common invocations). In Ruby, === is case subsumption.
Here's the description of === from Object: "Case Equality -- For class Object, effectively the same
as calling #==, but typically overridden by descendants
to provide meaningful semantics in case statements."
Sadly, even though it is comprised of three =, it doesn't have anything even remotely to do with equality :-D

Ruby ternary operator without else

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

Best ruby idiom for "nil or zero"

I am looking for a concise way to check a value to see if it is nil or zero. Currently I am doing something like:
if (!val || val == 0)
# Is nil or zero
end
But this seems very clumsy.
Objects have a nil? method.
if val.nil? || val == 0
[do something]
end
Or, for just one instruction:
[do something] if val.nil? || val == 0
From Ruby 2.3.0 onward, you can combine the safe navigation operator (&.) with Numeric#nonzero?. &. returns nil if the instance was nil and nonzero? - if the number was 0:
unless val&.nonzero?
# Is nil or zero
end
Or postfix:
do_something unless val&.nonzero?
If you really like method names with question marks at the end:
if val.nil? || val.zero?
# do stuff
end
Your solution is fine, as are a few of the other solutions.
Ruby can make you search for a pretty way to do everything, if you're not careful.
First off I think that's about the most concise way you can check for that particular condition.
Second, to me this is a code smell that indicates a potential flaw in your design. Generally nil and zero shouldn't mean the same thing. If possible you should try to eliminate the possibility of val being nil before you hit this code, either by checking that at the beginning of the method or some other mechanism.
You might have a perfectly legitimate reason to do this in which case I think your code is good, but I'd at least consider trying to get rid of the nil check if possible.
You can use the Object.nil? to test for nil specifically (and not get caught up between false and nil). You can monkey-patch a method into Object as well.
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
This is not recommended as changes to Object are difficult for coworkers to trace, and may make your code unpredictable to others.
nil.to_i returns zero, so I often do this:
val.to_i.zero?
However, you will get an exception if val is ever an object that does not respond_to #to_i.
I believe your code is incorrect; it will in fact test for three values: nil, false, and zero. This is because the !val expression is true for all values that are false, which in Ruby is nil and false.
The best I can come up with right now is
if val == nil || val == 0
# do stuff
end
Which of course is not very clever, but (very) clear.
My solution also use Refinements, minus the conditionals.
module Nothingness
refine Numeric do
alias_method :nothing?, :zero?
end
refine NilClass do
alias_method :nothing?, :nil?
end
end
using Nothingness
if val.nothing?
# Do something
end
Short and clear
[0, nil].include?(val)
Shortest and best way should be
if val&.>(0)
# do something
end
For val&.>(0)
it returns nil when val is nil since > basically is also a method, nil equal to false in ruby. It return false when val == 0.
Rails does this via attribute query methods, where in addition to false and nil, 0 and "" also evaluate to false.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
However it has its share of detractors. http://www.joegrossberg.com/archives/002995.html
To be as idiomatic as possible, I'd suggest this.
if val.nil? or val == 0
# Do something
end
Because:
It uses the nil? method.
It uses the "or" operator, which is preferable to ||.
It doesn't use parentheses, which are not necessary in this case. Parentheses should only be used when they serve some purpose, such as overriding the precedence of certain operators.
I deal with this by defining an "is?" method, which I can then implement differently on various classes. So for Array, "is?" means "size>0"; for Fixnum it means "self != 0"; for String it means "self != ''". NilClass, of course, defines "is?" as just returning nil.
You can use case if you like:
case val with nil, 0
# do stuff
end
Then you can use anything that works with ===, which is nice sometimes. Or do something like this:
not_valid = nil, 0
case val1 with *not_valid
# do stuff
end
#do other stuff
case val2 with *not_valid, false #Test for values that is nil, 0 or false
# do other other stuff
end
It's not exactly good OOP, but it's very flexible and it works. My ifs usually end up as cases anyway.
Of course Enum.any?/Enum.include? kind of works too ... if you like to get really cryptic:
if [0, nil].include? val
#do stuff
end
The right thing to do is of course to define a method or function. Or, if you have to do the same thing with many values, use a combination of those nice iterators.
I really like Rails blank? method for that kind of things, but it won't return true for 0. So you can add your method:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
And it will check if some value is nil or 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Instead of monkey patching a class, you could use refinements starting in Ruby 2.1. Refinements are similar to monkey patching; in that, they allow you to modify the class, but the modification is limited to the scope you wish to use it in.
This is overkill if you want to do this check once, but if you are repeating yourself it's a great alternative to monkey patching.
module NilOrZero
refine Object do
def nil_or_zero?
nil? or zero?
end
end
end
using NilOrZero
class Car
def initialize(speed: 100)
puts speed.nil_or_zero?
end
end
car = Car.new # false
car = Car.new(speed: nil) # true
car = Car.new(speed: 0) # true
Refinements were changed in the last minute to be scoped to the file. So earlier examples may have shown this, which will not work.
class Car
using NilOrZero
end
This is very concise:
if (val || 0) == 0
# Is nil, false, or zero.
end
It works as long as you don't mind treating false the same as nil. In the projects I've worked on, that distinction only matters once in a while. The rest of the time I personally prefer to skip .nil? and have slightly shorter code.
[Update: I don't write this sort of thing any more. It works but is too cryptic. I have tried to set right my misdeeds by changing the few places where I did it.]
By the way, I didn't use .zero? since this raises an exception if val is, say, a string. But .zero? would be fine if you know that's not the case.
This evaluates to true for nil and zero: nil.to_s.to_d == 0
unless (val || 0).zero?
# do stufff
end
In a single stretch you can do this:
[do_something] if val.to_i == 0
nil.to_i will return 0
Another solution:
if val.to_i == 0
# do stuff
end
val ||= 0
if val == 0
# do something here
end

Resources