As per && - Crystal, z = x && y is syntactically the same as:
tmp = x
z = if tmp
y
else
tmp
end
In order to actually turn two String? into a Bool, you’d prob want to do like z = !x.nil? && !y.nil? (or maybe even #presence). Could also shorten that up to z = !!(x && y) as well, but at the cost of readability/not handling empty strings if that’s important.
Also worth pointing out, if you’re using this as part of an if statement, then you can just do if x && y due to Truthy and falsey values - Crystal, only really need a direct Bool if you want to pass that variable around/reuse it.
grunt Well that’s that, guess I’ll have to get used to !! then.
I do think the argument is a bit weak, though. If having #truthy? as an alternative to !! is considered superfluous, why do we have #nil?? x == nil should evaluate the same.
v = 1 || nil
pp typeof(v) # => (Int32 | Nil)
unless v == nil
pp typeof(v) # => (Int32 | Nil)
end
unless v.nil?
pp typeof(v) # => Int32
end
I think the key difference in this context is .nil? is a pseudo compiler method which allows the compiler to change/guarantee the type of a variable. Whereas #== is a simple method that can be overridden to do something like nil == nil # => false or nil != nil # => true, hence why in this example the type of v is still Int32 | Nil.