Operator to evaluate class as Boolean in truthy contexts

I know that the Kotlin team much prefers explicit over implicit, however I do believe that this could be a feature used well in moderation. This feature can be found in python, you can define __bool__ in a class and the result of bool(thing) (which, of course, returns a boolean) will be put in place of thing when evaluating it in a truthy context.

class BooleanWrapper:
    def __init__(self, value: bool):
        self.value: bool = value
    def __bool__(self) -> bool:
        return value

truthy = BooleanWrapper(false)
if truthy:
    print("The truth has been revealed!")
else:
    print("The false gods still roam...")

This is not much more than a quick thought I had while writing part of my project and using BooleanWrapper.value a lot (im using sealed class to represent several states of the booleans access status, hence why I am not using an inline class for this case), I’m sure that this could be improved on especially related to possible ambiguity, though the amount of ambiguity in a program is almost entirely dependent on the programmer and not the language!

sealed class BooleanWrapper(val value: Boolean) {
    operator fun booleanize(): Boolean {
        ... // intermediate logic
        return value
    }
}

val truthy = BooleanWrapper(false)

if (truthy) { // == true is implicit here because BooleanWrapper
    ...
}
2 Likes

Perhaps the most idiomatic equivalent would be for the compiler to check whether the result of an expression in if () or while () had a toBoolean() method that returned a Boolean, and if so, call that. (In a similar way to how Java and Kotlin call toString() when doing string concatenation on something that’s not already a String.)

Not sure whether that would be useful enough to justify the language change, though. I can’t recall any situations where I’d have wanted to use it; in practice, you tend to use a Boolean-valued function or property (e.g. if (action.isCompleted())), whose name makes the code more readable. And of course you can already write and call a toBoolean() method explicitly if there’s no better name.

2 Likes

I’ve always hated this, even in Python. Should be explicit.
People often rely on this and don’t take into account all the possibilities that a “false” collection could be; they just assume “null” or empty, but often don’t consider both.

2 Likes

I’m not saying this should be an operator implemented in to data types in the stdlib. We already have isNullOrEmpty() for checking if a collection is null or empty (though I don’t see why this couldn’t be a replacement, but this is coming from a python developer), plus we have other better ways of checking anything else.

This should be up to the developer to implement in their own classes, and if ambiguity arises then the developer needs to rethink how they implemented it.

I think it definitely does have it’s place in the realm of say, sealed class boolean wrappers (they cant get the implied functionality of a boolean like inline class wrapper(val value: Boolean) does, but they do have the functionality of a class) or objects whose main usage is to be evaluated as a boolean…

2 Likes