kotlin when 表达式自动转换

kotlin when expression autocast

我希望以下 kotlin 代码能够工作:

val result: Try<Option<String>> = Success(Some("test"))

val test = when {
    result is Success && result.value is Some -> result.value.t // not working
    result is Success && result.value is None -> "Empty result"
    result is Failure -> "Call failed!"
    else -> "no match!"
}

我将箭头库用于 Try 和 Option monad。

不幸的是,我只能访问第一个条件 "is Success" 而不是第二个条件 "is Some" 的值。所以,我只能做 "result.value",然后我得到一个字符串选项。

我错过了什么吗?这将为我节省很多内部“.map”和“.fold”调用。

更新:

我要先投,太丑了:

result is Success && result.value is Some -> (result.value as Some<String>).t

你可以这样简化模式匹配:

val test = result
  .map { it.getOrElse { "Empty result"} }
  .getOrElse { "Call failed!" }

哪个更详尽,不需要 else 替代方案

或者,如果您不关心抛出的异常,您可以在 Try:

上使用 toOption
val test = result
  .toOption()
  .getOrElse { "No value!!" }

但是,这有一些明显的信息丢失。

我个人会将 Try 实例冒泡给结果的消费者,用 .map 折叠内部 Option 以便最终结果的类型为 Try<String> 让消费者处理错误。

但是,这在很大程度上取决于问题的实际上下文。

我使用 Kotlin 1.3.21 在 IntelliJ 中尝试了您的示例。 它显示了问题的原因:

您需要将 result.value 提取为变量才能使其正常工作。我找到了以下代码片段来解决它


val result: Try<Option<String>> = Success(Some("test"))

val test = when (result) {
    is Success -> when(val value = result.value) {
        is Some -> value.t
        is None -> "None"
    }
    is Failure -> "Call failed!"
    else -> "no match!"
}

我使用 Kotlin 1.3.x when 和声明语法。

您也可以使用箭头 API 来获得类似的结果:

val test = result.fold(
    ifSuccess = { it.getOrElse { "None" }},
    ifFailure = { "Call failed!" }
)

在这里你不需要在when中有else子句。