Hassaan
09/01/2022, 11:03 AMreadLine().toBoolean() returns a Boolean type
and
readLine().toInt() throws a compile type error
Rob 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 IllegalArgumentException
Rob 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.