What do I need to do to a struct to use it in a boolean context?

What do I need to do to a struct to use it in a boolean context?

julia> struct Foo
       bool::Bool
       end

julia> if Foo(true)
       println("How do I make this work?")
       end
ERROR: TypeError: non-boolean (Foo) used in boolean context
Stacktrace:
 [1] top-level scope

Note that the original poster on Slack cannot see your response here on Discourse. Consider transcribing the appropriate answer back to Slack, or pinging the poster here on Discourse so they can follow this thread.
(Original message :slack:) (More Info)

2 Likes

You can’t. Only Bool can be used in a boolean context.

(In principle, we could add an AbstractBool supertype of Bool and allow any AbstractBool in a boolean context, and/or add istrue/isfalse functions that you could overload.)

3 Likes

If it’s too much setup for the application, this should also work

if Foo.bool
       println("How do I make this work?")
end

I can think of other places where sub typing from AbstractBool (or implementing istrue or isfalse as appropriate for if statements) would simplify things. I think it would be a useful addition.

I’m working a large codebase that has deployed Bools in e.g. structs and has accessed those bools elsewhere in the code in if statements. However, pointers to those structs are also passed to a c library which expects the Bools to be 32 bit ints, where it only cares about the first bit. The problem is that it struct is the wrong size and I get a segfault.

Two solutions were proposed:

  1. Keep the structs as they are and use convert at the point of the ccall. E.g.:
struct Foo
  bar::Bool
  baz::Bool
end

struct Foo_ccall
  Bar::Cint
  Baz::Cint
end
Base.convert(::Type{Foo_ccall}, foo::Foo) = Foo_ccall(Cint(foo.bar), Cint(foo.baz))

and use the ccall via

foo = Foo(true, false)#
output = ccall(func, ReturnType, (Ref{Foo_ccall},), foo)

rather than the original

output = ccall(func, ReturnType, (Ref{Foo},), foo)
  1. Swap out the Bools in the structs for Cints and refactor the if statements.

I ended up doing 1) to make sure that I was solving the right problem and then 2) because the technical debt had to be paid at some point.