Determining Truthiness of an expression?
You could try (true & value) == value
. The part in parentheses seems to always return a boolean; if the value wasn't originally a bool, then it won't be equal to the result. A bool, however, will.
What evaluates to false in Ruby?
false
and nil
are the only ones:
http://www.ruby-doc.org/core-2.1.1/FalseClass.html
Rails provides present?
which also includes empty strings and empty arrays: http://api.rubyonrails.org/classes/Object.html#method-i-present-3F
YARD convention for truthiness
Using anything other than Boolean would imply that you're doing some sort of special handling, like interpreting 0
as false or something less literal than true/false checking.
You can see the convention used in the YARD docs where Boolean
represents both the TrueClass
and FalseClass
types. This type does not
exist in Ruby, however.
Trying to use .reduce to return true if there are truthy values else false if there are falsey values
You need to understand the difference between "truthiness"/"falsiness" and being true
/false
.
Ruby would evaluate everything that is not nil
or false
as truthy, so you can write:
puts 1 if 1
and it will puts 1.
In this assignment you're asked to use truthiness, so instead of comparing to true
you can use ruby to do the conversion for you using double negation !!
:
pry> [1, "2", nil, true, false].map{|e| !!e}
=> [true, true, false, true, false]
Also note that a block in reduce
accepts two params - one is the current element and another one is accumulator - the result of interating over previous elements. Use both in the block, otherwise you'll be returning result depending only on the last element of the array.
With Ruby Booleans, what are you checking for if there are no equality statements?
This is a common paradigm in programming, not a Ruby abstraction. You are checking if something is truthy. In ruby in particular, everything is truthy except false
and nil
. Try it yourself in your console if you want to test this:
!!1 # => true
!!0 # => true
!![] # => true
!!{} # => true
...etc, whereas
!!false # => false
!!nil # => false
Important note: this is only the case for Ruby. Other languages have different rules. For example, in some languages 0
is falsy. It's important to learn these early on when learning a new language.
Best way to test if a variable is nil or false implicitly
def truthiness(value)
if value
"truthy"
else
"falsy"
end
end
puts "nil:", truthiness(nil) # falsy
puts "false:", truthiness(false) # falsy
puts "true:", truthiness(true) # truthy
puts "[]:", truthiness([]) # truthy
puts "{}:", truthiness({}) # truthy
puts "0:", truthiness(0) # truthy
I know you know Python, so I can say that:
In Python, None, False, and empty containers such as [], {}, and even 0 are all falsy.
In Ruby, nil and false are falsy, whereas most other things are truthy, even [], {}, and 0.
Make a NullObject evaluate to falsy in Ruby
I think you have only halfway adopted that pattern, and have not correctly adopted its spirit. My understanding is that the very purpose of the pattern is to avoid ||
.
You should have some purpose for calling current_user || redirect_out
, and that could be doing something with it, or getting some attribute of it. For example, suppose your code has:
(current_user || redirect_out).foo
When current_user
is not an instance of Null::User
, you wanted to call foo
on it. In that case, what you should do is define Null::User#foo
to be redirect_out
(possibly followed by some more operations like foo
on other classes).
class Null::User
def foo; redirect_out ... end
end
and in place of (current_user || redirect_out).foo
, you should just do
current_user.foo
When current_user
is not a Null::User
instance, it will call foo
. When it is such instance, then the redirect_out ...
routine will be called on it.
Ruby Enumerable: first truthy value of a block
it does the job, but is the simplest way? Is it efficient compare to
simply using a each and caching the value?
Simplest way?
We can define this method :
def first_truthy_block(enumerable, &block)
enumerable.lazy.map(&block).find(&:itself)
end
Here in action :
array = [0,1,2,3,4,:x5,'abc']
puts first_truthy_block(array) { |x|
if x ** 2 > 10 then
"ARTWORK with #{x}!!!"
end
}
#=> ARTWORK with 4!!!
Could it be simpler?
enumerable
is needed, it's the object you're working on.lazy
is needed, it wouldn't stop as soon as possible, and would throw an exception with:x5**2
.- map is needed, you need to apply some method to your element
- find is needed to extract one value at most out of your enumerable
With standard Enumerable
methods, I don't see how it could be any simpler.
Is it efficient?
It is slower than your each
method. It does basically the same thing and should have the same complexity but it does use more method calls and creates more objects :
require 'fruity'
def first_truthy_block_lazy(enumerable, &block)
enumerable.lazy.map(&block).find(&:itself)
end
def first_truthy_block_each(enumerable, &block)
enumerable.each do |item|
result = block.call(item)
return result if result
end
nil
end
big_array = Array.new(10_000){rand(4)} + [5] + Array.new(10_000){rand(20)} + [:x, :y, 'z']
compare do
_lazy_map do
first_truthy_block_lazy(big_array) { |x|
if x ** 2 > 10 then
"ARTWORK with #{x}!!!"
end
}
end
_each do
first_truthy_block_each(big_array) { |x|
if x ** 2 > 10 then
"ARTWORK with #{x}!!!"
end
}
end
end
fruity returns :
Running each test once. Test will take about 1 second.
_each is faster than _lazy_map by 3x ± 0.1
Why Treat 0 as True in Ruby?
I'm guessing that Matz wanted conceptual simplicity of "truthiness" as such - the only "false" values are false
and nil
. Period.
Using just false
would be the cleanest but there is understandable need for including nil
. To include the integer zero as a special case might open the mental floodgates of questioning truthiness of other types. What about strings, is ""
false? And arrays, is []
false? And hashes, is {}
false? Ad insanitum (see JavaScript)...
Related Topics
Capistrano 3 Change Ssh_Options Inside Task
Symbol#To_Proc with Custom Methods
How to Decode Q-Encoded Strings in Ruby
Can't Run Bundle Update on Windows
Time Gt Query Not Working with Mongoid and Ruby on Rails
Optional Parens in Ruby for Method with Uppercase Start Letter
Ruby on Rails - Doesn't Create Script/Server
Nokogiri: Searching for <Div> Using Xpath
Consequences of Implementing To_Int and To_Str in Ruby
How to Correctly Install Rvm in Docker
Rails 5 Db Migration: How to Fix Activerecord::Concurrentmigrationerror
Storing Passwords for External APIs - Best Practice
Ruby on Rails 4 - Simple_Form Multiple Select Input
Does Ruby Have Syntax for Safe Navigation Operator of Nil Values, Like in Groovy