Kristian Nedrevold
10/07/2022, 12:38 AMfun foo(): String? = if ((0..1).random() == 1) "Hello World" else null
fun bar(s: String): String? = if ((0..1).random() == 1) s else null
fun maybe(foo: () -> String?, bar: (input: String) -> String?): Either<Err, String> =
foo()?.let { first ->
bar(first)?.let { second ->
Either.Right(second)
} ?: Either.Left(Err("Could not find second"))
} ?: Either.Left(Err("Could not find first"))
maybe(::foo, ::bar)
Kristian Nedrevold
10/07/2022, 12:44 AMprivate fun CollectionMetadata.getMrsJdbcTypeForColumn(
tableName: String,
columnName: String): Either<MrsJsonReaderError, JDBCType> = tables.firstOrNull {
it.name == tableName
}?.let { table -> table.columns.firstOrNull {
it.name == columnName
}?.let { column -> Either.Right(column.jdbcType) }
?: Either.Left(MrsJsonReaderError.MrsColumnNameNotInMetadataForTable(tableName, columnName))
} ?: Either.Left(MrsJsonReaderError.MrsTableNameNotInMetadata(tableName))
carbaj0
10/07/2022, 4:27 AMprivate suspend fun CollectionMetadata.getMrsJdbcTypeForColumn(
tableName: String,
columnName: String
): Either<MrsJsonReaderError, JDBCType> =
either {
val table =
tables.firstOrNull()
?: shift(MrsJsonReaderError.MrsTableNameNotInMetadata(tableName))
val column =
table.columns.firstOrNull { it.name == columnName }
?: shift(MrsJsonReaderError.MrsColumnNameNotInMetadataForTable(tableName, columnName))
column.jdbcType
}
carbaj0
10/07/2022, 4:36 AMprivate fun CollectionMetadata.getMrsJdbcTypeForColumn(
tableName: String,
columnName: String
): Either<MrsJsonReaderError, JDBCType> =
tables.firstOr(MrsJsonReaderError.MrsTableNameNotInMetadata(tableName)) {
it.name == tableName
}.flatMap { table ->
table.columns.firstOr(MrsJsonReaderError.MrsColumnNameNotInMetadataForTable(tableName, columnName)) {
it.name == columnName
}.map { column ->
column.jdbcType
}
}
public inline fun <E, T> Iterable<T>.firstOr(error: E, predicate: (T) -> Boolean): Either<E, T> {
for (element in this) if (predicate(element)) return element.right()
return error.left()
}
Kristian Nedrevold
10/07/2022, 6:34 AMstojan
10/07/2022, 11:44 AMeither
computation block + ensureNotNull
either<String, String> {
val first = ensureNotNull(foo()) { "First is null" }
val second = ensureNotNull(bar(first)) { "Second is null" }
second
}
I used a plain string instead of Errphldavies
10/07/2022, 11:51 AMprivate suspend fun CollectionMetadata.getMrsJdbcTypeForColumn(
tableName: String,
columnName: String
): Either<MrsJsonReaderError, JDBCType> = either {
val table = ensureNotNull(tables.firstOrNull { it.name == tableName }) {
MrsJsonReaderError.MrsTableNameNotInMetadata(tableName)
}
val column = ensureNotNull(table.columns.firstOrNull { it.name == columnName }) {
MrsJsonReaderError.MrsColumnNameNotInMetadataForTable(tableName, columnName)
}
column.jdbcType
}
Also of note, the firstOr
extension proposed would create the error instance even if it’s not used. That may or may not be an issue for you and is unlikely to have much of a performance impact but worth pointing out (whereas the ensureNotNull
lazily instantiates it only when required)phldavies
10/07/2022, 11:59 AMensureNotNull
defines a contract for smart-casting and unwrap it’s usage:
private suspend fun CollectionMetadata.getMrsJdbcTypeForColumn(
tableName: String,
columnName: String
): Either<MrsJsonReaderError, JDBCType> = either {
val table = tables.find { it.name == tableName }
ensureNotNull(table) { MrsJsonReaderError.MrsTableNameNotInMetadata(tableName)}
val column = table.columns.find { it.name == columnName }
ensureNotNull(column) { MrsJsonReaderError.MrsColumnNameNotInMetadataForTable(tableName, columnName) }
column.jdbcType
}
This (and using find
in place of firstOrNull
) keeps the intent of the code nice and clear at each stage.Kristian Nedrevold
10/07/2022, 4:36 PM