How to Bool

So far I’ve been content with using as true and nil as false in conditionals.

But now I want a Bool var but discover that (assume x and y are String?):

z : Bool = (x && y).as(Bool)

Gives me “Error: can’t cast (String | Nil) to Bool”.

Of course I can:

z : Bool = x && y ? true : false

But that feels very clunky. Aren’t there a better way?

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.

Oh yeah, I know of the joys of truthy/falsy values. It’s refreshingly simple compared to PHP/JS.

But I’d hoped that double negation would stick to roaming the JS world.

I was hoping for something simple ala (Object | Nil)#to_b (or (Object | Nil)#thruthy? would make sense).

Bool is probably a bit overlooked due to the fact that one doesn’t really need it 99% of the time…

Related: Add a .to_bool method? · Issue #7538 · crystal-lang/crystal · GitHub

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.

shrugs

https://play.crystal-lang.org/#/r/fi89

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.

2 Likes