Boolean to number in Lua - lua

Is there a way to get 1 with true and 0 with false in Lua?
There is the tobool which gives true or false with 1 or 0, but tonumber gives a nil value with true or false.

You can combine and and or clauses like ternary operators.
function bool_to_number(value)
return value and 1 or 0
end

You can also do this:
bool_to_number={ [true]=1, [false]=0 }
print(bool_to_number[value])
Or this:
debug.setmetatable(true, {__len = function (value) return value and 1 or 0 end})
print(#true)
print(#false)

The answer from hjpotter92 takes any value different to nil as a true value (returning 1). This instead takes the value true or false.
local value = true
print(value == true and 1 or value == false and 0)
-- we add the false check because it would drop 0 in case it was nil
If you want to use a function instead, this would be it
local value = true
local function bool_to_number(value)
return value == true and 1 or value == false and 0
end
print(bool_to_number(value))

Related

redis script check if hash field exists

The question is about lua script in redis.
I'm trying to check if some field exists in a hash table, but the return value of redis.call suprised me:
EVAL 'local label = "oooo"; local tesid = redis.call("HGET", "nosuchkey", "nosuchfield"); if tesid == nil then label="aaaa" elseif tesid == "" then label="bbbb" else label = "kkkk" end; return {tesid,label}' 0
the return value is
1) (nil)
2) "kkkk"
I don't understand why I got into that else branch -- where label is set to "kkkk" -- when tesid is nil, I think it should output "aaaa".
Why does the script go into "kkkk" label?
For better reading, I paste the script here:
local label = "oooo"
local tesid = redis.call("HGET", "nosuchkey", "nosuchfield")
if tesid == nil
then
label="aaaa"
elseif tesid == ""
then
label="bbbb"
else
label = "kkkk"
end
return {tesid,label}
Short Answer: tesid is false NOT nil.
Redis' conversion rules for nil reply is as follows:
Redis nil reply is converted to Lua false boolean type.
Lua false boolean type is converted to Redis' nil reply.
In your case, HGET returns nil, which is converted to false. So tesid is false. It's not equal to either nil or "", so label is set to kkk. When your code returns tesid as part of the return value, it's converted to Redis' nil reply. And that's why you got {nil, kkk}

Lua, if statement idiom fails to return proper boolean

local a = (true==true) and false or nil -- returns nil
local a = (true==true) and true or nil -- returns true
local a = (true==true) and not false or nil -- returns true
local a = (true==true) and not true or nil -- returns nil
Returns proper boolean when value is true, but fails when false. Why?
The boolean idiom works by using short-cut evaluation (only evaluate the second operand when necessary).
If you rewrite the expressions with explicit precedence you can see why you would get nil:
(true and false) or nil => false or nil => nil
(true and true) or nil => true or nil => true
(true and not false) or nil => true or nil => true
(true and not true) or nil => false or nil => nil
The Logical Operators section of Programming in Lua explains the idiom:
Another useful idiom is (a and b) or c (or simply a and b or c, because and has a higher precedence than or), which is equivalent to the C expression
a ? b : c
provided that b is not false. For instance, we can select the maximum of two numbers x and y with a statement like
max = (x > y) and x or y
Why can b not be false? Because the evaluation will always return false.
1 > 0 and false --> false
1 < 0 and false --> false

Can't use where on a column with nil value

I have an Article model
Article.last.publish
=> nil
Article.last.publish != true
=> true
Article.where("publish != ?", true)
=> []
Why am I getting an empty array there?
There are only 2 falsy values in ruby : false and nil
So, if you check the value of !nil then the output will be true
So with your first statement
Article.last.publish # its output is nil
Then your second statement
Article.last.publish != true # this is correct , since !nil = true
But the last one
Article.where("publish != ?", true)
gets converted into a query as
SELECT `articles`.* FROM `articles` WHERE (publish != 1)
which means all articles whose publish value is not true, which means false
and false is not equal to nil.
nil and false are two different falsy values.
Try Article.where(publish: false)

One-line assignment: If (condition) variable = value1 else value2

How do I do something like this?
if params[:property] == nil
#item.property = true
else
#item.property = false
Always forget the proper syntax to write it in one line.
In PHP it would be like this:
#item.property=(params[:property]==nil)true:false
Is it the same in rails?
use the ternary operator:
#item.property = params[:property] ? true : false
or force a boolean conversion ("not not" operation) :
#item.property = !!params[:property]
note : in ruby, it is a common idiom not to use true booleans, as any object other than false or nil evaluates to true.
m_x answer is perfect but you may be interested to know other ways to do it, which may look better in other circumstances:
if params[:property] == nil then #item.property = true else #item.property = false end
or
#item.property = if params[:property] == nil then true else false end

Ruby lazy if statement with no operator

Is it possible to do this in ruby?
variablename = true
if variablename
puts "yes!"
end
Instead of this
variablename = true
if variablename == true
puts "yes!"
end
Edit:
also considering having:
variablename = 0 #which caused my problem
I can't get that to work. Is such a style of saying if possible? I'm learning ruby now, and it is possible in PHP but im not sure how to do it right in ruby
sure, it's possible
everything except nil and false is treated as true in ruby. Meaning:
var = 0
if var
# true!
end
var = ''
if var
# true!
end
var = nil
if var
# false
end
xdazz and Vlad are correct with their answers, so you would need to catch 0 separately:
variable = false if variable.zero? # if you need 0 to be false
puts "yes!" if variable # now nil, false & 0 will be considered false
It's possible at all. In ruby, only nil and false is considered as false, any other value is true.

Resources