Hassaan
09/01/2022, 11:03 AMreadLine().toBoolean() returns a Boolean type
and
readLine().toInt() throws a compile type errorRob Elliot
09/01/2022, 11:05 AMfun readLine(): String? returns the type String? - i.e. either null or a String.
The extension function fun String?.toBoolean(): Boolean is defined with a receiver of type String?, so it works.
The extension function fun String.toInt(): Int is defined with a receiver of type String, so it will not work.
You need to do readLine()?.toInt(), which will return type Int?.Rob Elliot
09/01/2022, 11:07 AMtoBoolean on String? - I think it should have been on String.Klitos Kyriacou
09/01/2022, 11:32 AMString.toInt() throws an exception if the string is not an Int, but toBoolean() just returns false if you give it any old rubbish.Rob Elliot
09/01/2022, 11:36 AMpublic static boolean parseBoolean(String s) {
return "true".equalsIgnoreCase(s);
}
Anything other than "true", including null, translates to false.Rob Elliot
09/01/2022, 11:36 AMtoInt) is better because you find out faster that "yes" (for instance) evaluates to false.Joffrey
09/01/2022, 1:47 PM"TRUE".toBoolean() actually does evaluate to true
https://pl.kotl.in/Xcw95xfyRRob Elliot
09/01/2022, 1:49 PMequalsIgnoreCase call...Rob Elliot
09/01/2022, 1:52 PMfun String.toBoolean(): Result<Boolean> = when {
this == "true" -> Result.success(true)
this == "false" -> Result.success(false)
else -> Result.failure(IllegalArgumentException("Cannot parse $this to boolean"))
}
fun String.toBooleanOrNull(): Boolean = this.toBoolean().getOrNull()
though that's breaking convention too - but personally I prefer the compiler to rap me over the knuckles about parsing failure.Joffrey
09/01/2022, 1:53 PMRob Elliot
09/01/2022, 1:53 PMJoffrey
09/01/2022, 1:53 PMRob Elliot
09/01/2022, 1:59 PMval unvalidatedInput = "not parseable"
if (unvalidatedInput.toBoolean()) {
// do something
}
Returning a Result<Boolean> it does not compile, forcing me to think about how to handle unvalidated input before it hits production. Which might just be making a conscious decision to use unvalidatedInput.toBooleanOrNull() ?: false - but it's switched me from not thinking about it to thinking about it.
(I should have written a test of course, but even then the unthinking thing is to check it with the parseable values, it's easy to forget to write a test with unparseable input. I'd love to be able to claim I'm immune to these sorts of mistakes but bitter experience shows I'm not.)ephemient
09/01/2022, 4:28 PM.toBooleanStrict() and .toBooleanStrictOrNull() unless you specifically want the legacy "true"::equals behavior. that makes the following pairs act analogously:
readLine()?.toBooleanStrict()
readLine()?.toInt()
readLine()?.toBooleanStrictOrNull()
readLine()?.toIntOrNull()ephemient
09/01/2022, 4:29 PMResult-returning type is not good - it doesn't indicate that the only possible failure is IllegalArgumentExceptionRob Elliot
09/02/2022, 8:10 AMfun toBooleanStrict(): Boolean - the type signature leaves the user to inspect the documentation to find out it fails at all, let alone what it fails with, though the name is an indicator.
I like an Either type specialised to represent the a success or failure, I even rolled my own (had to call it an Outcome as Result clashed):
https://github.com/Mahoney-playground/goos/blob/1a7207345f98f83caa4f3c5ad03de96f726e1d10/gradle/build-plugins/extract-plugin/src/either/Outcome.kt
But for reasons I don't fully understand that seems an unpopular approach in the Kotlin community.Joffrey
09/02/2022, 8:27 AMRob Elliot
09/02/2022, 8:39 AMfun String.toBoolean(): Outcome<IllegalArgumentException, Boolean>, and secondly because I think they are a major source of bugs - it's just too easy to forget to validate your inputs.