Ruby- Beginner ran into unknown syntax - ruby

Trying to learn Ruby I ran into this kind of syntax.... Can anyone explain me what it means?
a = nil if b.nonzero?
nonzero? : Returns self if num is not zero, nil otherwise.
And thus does not return a boolean

Values in ruby are truthy and falsey. That is, if a value is not nil, or false, it is true. So if you have a function that returns 1, you can use that in a boolean expression some_function && true would resolve true.
Likewise, if it returned nil, some_function && true would return false.
There's a detailed and in depth explanation here: https://gist.github.com/jfarmer/2647362

Related

Why does '||' operator return '[ ]'?

I tested this on console:
[] || 1 # => []
Shouldn't it return the value that exits, and not []? I can change it to ternary operator, which works fine, but why does the condition above not work?
Because [] is truthy value in Ruby, so the second part of your expression is never executed, it always evaluates to []. In Ruby, just false and nil aren't truthy.
Oh, anyway, you don't need that. map returns an empty array if the array is empty.
Model.new(
name: abc.name,
description: abc.description,
product_ids: abc.product_ids.map(&:id)
)
The exact semantics of || are:
if first expression is not nil or false, return it
if first expression is nil or false, return the second expression
So since [] is truthy it will evaluate to [], as explained by #Ursus.

Lua - Error in execution of return and or

I am basically doing some testing to get to know the Lua language a bit better. I found a bug that makes zero sense to me.
Function:
local function d(c)
return (!c and print("c", false) or print("c", true))
end
local function a(b, c)
return (!b and d(c) or print("b", true))
end
When i run a(1, nil) or a(1, 1) it outputs b true, but if i run a(nil, 1) then it outputs c true and b true
If anyone could enlighten me on why it returns two value when that technically shouldn't be possible?
Maybe you already understand what's happening, but I've already written this post. Lua doesn't have a ! operator; I guess you meant not. (I wouldn't be surprised if someone has made a patched version of Lua with ! in place of not.)
a(nil, 1) returns not nil and d(1) or print("b", true). Now, not nil evaluates to true and d(1) evaluates to nil, so we have true and nil or print("b", true), which in turn evaluates to nil or print("b", true), and therefore print("b", true) is evaluated.
As to why d(1) evaluates to nil: it returns not 1 and print("c", false) or print("c", true). That is equivalent to not 1 and nil or nil because print always returns nothing when it is called, and nothing is treated as nil by the operators and and or. not x and nil or nil always evaluates to nil whether x is truthy or falsy, so d always returns nil. (The only difference is that if d receives a falsy value, both print calls are evaluated.)
You can verify that print returns nothing by calling type(print('a')): it throws the error "bad argument #1 to 'type' (value expected)", whereas type(nil) returns "nil".

Ruby disjunction syntax

I encountered some code that looks like:
(input_array || []).each do |a|
some stuff
end
What is the purpose of input_array || []? I would naively think that this would evaluate to a boolean value which would cause each to throw an error, but that's clearly not whats happening.
The semantics of || are:
if the first expression is not nil or false, return it
if the first expression is nil or false, return the second expression
This is used to provide a default value if the first is nil.

Implicit value of if/unless statement in ruby

I'm new to Ruby, and trying to understand why this works (it does seem to, at least according to "the Master"):
def array_of_fixnums?(array)
true unless array.find { |item| item.class != Fixnum }
end
My concern is where the "false-ness" is coming from when the array contains non-fixnum values. Am I right to assume there is no implicit "else false" in the unless statement? In that case I assume it must be coming from the nil value returned by Enumerable#find. Is that correct?
If so, that seems a bit shaky. Might it be better to return false explicitly, like this?
array.find { |item| item.class != Fixnum } ? false : true
Is there another, better way entirely? Thanks for helping me wrap my head around this, and for any "best practice" suggestions.
Your method is returning nil not because find returns nil, but because if your inline conditional does not pass, the method has no explicit return value. This would be more clear if it were not inline, consider:
def array_of_fixnums?(array)
unless array.find { |item| item.class != Fixnum }
return true
end
# otherwise don't explicitly return (implicit nil)
end
While relying on the falsiness of nil will often work, it is problematic in that it does not follow the principle of least surprise. A ? method should return true or false.
But your method has worse problems. It uses confusing logic (a double negative), and itself relies on the falsiness of nil and the truthiness of not nil, to function. Consider what happens if your method were passed [false]. Oops.
The better way would be something like:
array.all? {|n| n.is_a? Fixnum }
The reasoning is that this method does exactly what it says, plainly.
Returning a boolean explicitly, while not necessarily wrong, is superfluous and often considered bad practice. Rather consider the example, which says, in ruby speak, is every one of the values in this array a Fixnum?. The result of that expression is what the method is after; there's no reason to evaluate it then return true|false.
From the find method doc:
Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.
Thus, all you need is:
def array_of_fixnums?(array)
array.find { |item| item.class != Fixnum }
end
If anything is found, that will be returned, otherwise nil will be returned, and the method will evaluate do false.
However, as the item return could be an false or nil (if any item in the list is false or nil) I would recommend that you use the .any? method instead.
def array_of_fixnums?(array)
array.any? { |item| item.class != Fixnum }
end
Let's look at why true unless condition works as it does.
I believe x unless condition was provided as an esthetic improvement to x if !condition, but the two are equivalent (and, in my opinion, it is an improvement). To get rid of double-negatives, I'll just consider x if condition.
One of Ruby's basic tenets is that every statement must return a value (namely, the last expression evaluated). Therefore, x if condition must be evaluated as if condition then x else y end. But what is y? If y evaluated as true or false, x if condition would be meaningless when x is a boolean expression. To see why, consider:
w = (x == 5 if z == 6)
If w were true, we could conclude that x = 5 and z = 6, but if w were false, we wouldn't know whether z = 6 and x != 5, or z != 6 and x = 5 or x != 5. Considering that any value of y other than nil is evaluated as true or false, the only reasonable value for y is nil. That way, if w == nil is be available. Of course, this is still a problem (in other situations) when x could possibly be nil.
I would welcome clarification and elaboration. Perhaps there is also a less convoluted way of making this argument.

Why do method declarations evaluate to nil in ruby?

Defining a method doesn't seem to evaluate to a truthy value as can be checked by putting one inside an if condition:
if(def some_method; puts "random text"; end) then
puts "declaration evaluates to true"
else
puts "declaration evaluates to false"
end
# => declaration evaluates to false
Why/How does a method declaration evaluate to nil?
It actually evaluates to nil. This makes sense; why would a method creation return anything?
irb(main):001:0> def test; print 'test'; end
=> nil
However, it has to return something, so to return "nothing" would be to return nil.
Every statement in Ruby evaluates to something. The def statement's value is not supposed to be checked and is therefore nil.
You will find the behavior you are looking for in the reflective "meta-programming" method define_method.
class EmptyClass
m = define_method(:newmethod) {p "I am the new method"}
p m # => <Proc:0x50b3f359#E:\NetBeansProjects\RubyApplication1\lib\main.rb:6>
end
From Ruby gotchas:
Boolean evaluation of non-boolean data is strict: 0, "" and [] are all evaluated to true. In C, the expression 0 ? 1 : 0 evaluates to 0 (i.e. false). In Ruby, however, it yields 1, as all numbers evaluate to true; only nil and false evaluate to false. A corollary to this rule is that Ruby methods by convention — for example, regular-expression searches — return numbers, strings, lists, or other non-false values on success, but nil on failure. This convention is also used in Smalltalk, where only the special objects true and false can be used in a boolean expression.
Method definions such as def some_method; puts "random text"; end always return nil.
Now, that means the method is evaluated to nil. According to the Ruby Documentation:
Returns false if obj is nil or false; true otherwise.
Since your method return nil, if will evaluate it as false therefore execute the else statement.

Resources