Kotlin是否具有像Swift这样的Result类型

Zon*_*ame 1 types kotlin swift

Swift具有Result这样声明的类型

enum Result<Success, Failure: Error> {
    case success(Success)
    case failure(Failure)
}
Run Code Online (Sandbox Code Playgroud)

可以这样使用:

enum FooError: Error {
    case fizzReason
    case barReason
    case bazReason
}

func returnResult() -> Result<String, FooError> { 
    // ... Just imagine this method returns an error
}

switch returnResult() {
case .success(let string):
    print(s)
case .failure(.fizzReason):
    // do something
case .failure(.barReason):
    // do something
case .failure(.bazReason):
    // do something
}
Run Code Online (Sandbox Code Playgroud)

Kotlin是否具有可以以相同方式使用的类似数据类型?

Sma*_*ing 27

我不知道 Kotlin 是否有类似的东西,但这里有一个应该做同样的实现:

sealed class Result<out Success, out Failure>

data class Success<out Success>(val value: Success) : Result<Success, Nothing>()
data class Failure<out Failure>(val reason: Failure) : Result<Nothing, Failure>()
Run Code Online (Sandbox Code Playgroud)

实际例子:

fun echoString(string : String) : Result<String, Exception> {
    return if (string.isEmpty()) {
        Failure(Exception("Error"))
    } else {
        Success(string)
    }
}

fun main(args : Array<String>) {
    when(val result = echoString("string")) {
        is Success -> println(result.value)
        is Failure -> println(result.reason)
    }
}
Run Code Online (Sandbox Code Playgroud)


Mur*_*rph 7

有多种实现,但我知道的两个(并且我知道要积极维护)是:

  • Kotlin-result - 直接结果类型,非常灵活(README.md 中引用了其他实现)
  • Either in Arrow - Either 的 Kotlin 实现,可以用作结果。(Arrow有很多有趣的功能性东西)


Sah*_*nda 6

Kotlin的Result具有isFailureisSuccess等属性,这些属性基本上等同于Swift的Result。

摘要

结果,是Kotlin标准库中的一种类型,实际上是Kotlin功能执行成功与失败结果之间的有区别的联合-Success T | Failure Throwable,其中Success T表示某种T类型的成功结果,而Thailable Throwable表示具有任何Throwable异常的失败。为了提高效率,我们将其建模为标准库中的通用内联类Result。

局限性

结果不能用作Kotlin函数的直接结果类型,结果类型的属性也受到限制:例如

fun findUserByName(name: String): Result<User> // ERROR: 'kotlin.Result' cannot be used as a return type 
fun foo(): Result<List<Int>> // ERROR 
fun foo(): Result<Int>? // ERROR
var foo: Result<Int> // ERROR
Run Code Online (Sandbox Code Playgroud)

但是,允许使用在通用容器中使用Result类型或将结果作为参数类型接收的函数:

fun findIntResults(): List<Result<Int>> // Ok
fun receiveIntResult(result: Result<Int>) // Ok
Run Code Online (Sandbox Code Playgroud)

用法(在线运行)

class NumberNotEvenException(var number: Int) : Exception("$number not even") 

fun checkEvenNumbers(list: List<Int>): List<Result<Int>>{

    var returnList = mutableListOf<Result<Int>>()
    for (number in list){
        if (number%2==0){
            returnList.add(Result.success(number))
        }else{
            returnList.add(Result.failure(NumberNotEvenException(number)))
        }
    }
    return returnList
}


fun checkResult(result: Result<Int>){

    result.fold(onSuccess = { number ->
            println("$number is even")

    },onFailure = { 
        if (it is NumberNotEvenException){
            println("${it.number} is Odd")
          }
    })
}

fun main() {
    checkEvenNumbers((0..100).toList()).map {
            checkResult(it)
        }
}
Run Code Online (Sandbox Code Playgroud)

  • 从 Kotlin 1.5 开始,这些限制已被解除,您可以在代码中自由使用 Kotlin 的 Result monad,无需创建密封类。 (4认同)
  • 标准库中的结果类型几乎没有实际用途,因为它的存在是为了解决特定问题并且不能通用 - 请参阅此处:https://github.com/Kotlin/KEEP/blob/master/proposals/ stdlib/result.md#限制 (2认同)