Scala with Futures:
import java.util.UUID
import scala.concurrent.Future
trait User {
def isAdmin: Boolean
def id: UUID
}
trait Profile {
val accessLevel: Int
}
def createUser(user: User): Future[User] = ???
def createProfile(userId: UUID, profile: Profile): Future[Profile] = ???
def createAdminRights(admin: User, accessLevel: Int): Future[Unit] = ???
def create(newUser: User, newProfile: Profile): Future[Unit] = {
for {
user <- createUser(newUser)
profile <- createProfile(user.id, newProfile)
_ <- if (user.isAdmin) {
createAdminRights(user, profile.accessLevel)
} else {
Future.unit
}
} yield ()
}
object Main {
import scala.concurrent._
import scala.concurrent.duration._
def main(args: Array[String]): Unit = {
val user: User = ???
val profile: Profile = ???
Await.result(create(user, profile), 10.seconds)
}
}
Kotlin with Coroutines:
import java.util.*
interface User {
val isAdmin: Boolean
val id: UUID
}
interface Profile {
val accessLevel: Int
}
suspend fun createUser(user: User): User = TODO()
suspend fun createProfile(userId: UUID, profile: Profile): Profile = TODO()
suspend fun createAdminRights(admin: User, accessLevel: Int): Unit = TODO()
suspend fun create(newUser: User, newProfile: Profile) = {
val user = createUser(newUser)
val profile = createProfile(user.id, newProfile)
if (user.isAdmin) {
createAdminRights(user, profile.accessLevel)
}
}
object Main {
fun main(args: Array<String>) = runBlocking {
val user: User = TODO()
val profile: Profile = TODO()
create(user, profile)
}
}
Coroutine is like a variant of future or async monad in Scala, which makes the syntax terse, but its semantics are built into the language. Scala future or async monad is more versatile, as user can create their own async monad for different semantics, like Monix.