Search code examples
kotlinfold

Kotlin: Returning an object from a fold closure


I am building my first Kotlin Multiplatform app, I have not done Kotlin for a long time. The library I am using uses Folds (Aws Cognito: https://github.com/Liftric/cognito-idp)

I am trying to get the function below to return a User object however I am obviously missing how to use the fold()

    suspend fun getUser(accessToken: String) : User {
            
            provider.getUser(accessToken ).fold(
                onSuccess = {
                    print("login")
                    currentUser = User.populateUserDetails(it)

                   // Here is the error
                   return@fold currentUser
                },
                onFailure = {
                    // Handle exceptions
                    print(it.message)
                }
            )
        }

Type mismatch. Required:Unit. Found:User

How can I adjust the code above to return a User Object instead of a Unit object.

The framework uses folds everywhere which seems pointless if you can not return the data you requested.


Solution

  • A good place to start would be the documentation of fold:

    Returns the result of onSuccess for the encapsulated value if this instance represents success or the result of onFailure function for the encapsulated Throwable exception if it is failure.

    As you can see, fold itself returns a value, so you could return the whole expression by adding a return keyword in front:

    return provider.getUser(accessToken).fold(...)
    

    Now, in Kotlin, you don't need to use return within lambdas, as the last expression in the lambda is the value that is returned. Therefore, onSuccess could just be:

    onSuccess = {
        print("login")
        User.populateUserDetails(it)
    }
    

    (unless you really want to have side effects, which you shouldn't)

    So overall, you could write this:

    suspend fun getUser(accessToken: String) : User {
        return provider.getUser(accessToken).fold(
            onSuccess = {
                print("login")
                User.populateUserDetails(it)
            },
            onFailure = {
                // Handle exceptions
                print(it.message)
            }
        )
    }
    

    But taking a step back, depending on what you want to do with the error case, there are plenty of other Result helpers you could use here. See the list here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/