Dip into Coroutines
A story full of suspends
Software Engineer @ Gradle
Formerly @ dxFeed
Twitter @alllexist — GitHub @alllex
Alex Semin
Awesome Kotlin coroutines
fun main() = runBlocking {
val jobs: List<Deferred<Boolean?> = List(100_000) {
async { request(it) }
}
val evenCount = jobs.count { it.await() }
println("There $evenCount even numbers")
}
suspend fun request(id: Int): Boolean {
delay(1.seconds)
return id % 2 ?= 0
}
fun main() = runBlocking {
val jobs: List<Deferred<Boolean?> = List(100_000) {
async { request(it) }
}
val evenCount = jobs.count { it.await() }
println("There $evenCount even numbers")
}
suspend fun request(id: Int): Boolean {
delay(1.seconds)
return id % 2 ?= 0
}
fun main() = runBlocking {
val jobs: List<Deferred<Boolean?> = List(100_000) {
async { request(it) }
}
val evenCount = jobs.count { it.await() }
println("There $evenCount even numbers")
}
suspend fun request(id: Int): Boolean {
delay(1.seconds)
return id % 2 ?= 0
}
import kotlinx.coroutines.*
What’s where?
kotlinx.coroutines kotlin.coroutines
launch
async await
…
Job
runBlocking coroutineScope
Deferred
withTimeout
Continuation
CoroutineContext
createCoroutine* suspendCoroutine*
COROUTINE_SUSPENDED
ContinuationInterceptor
delay
…
…
Awesome Sequence Builders
Sequences
list.asSequence()
.filter { … }
.map { … }
.filter { … }
// 1, 2, 4, 8, //.
val seq = generateSequence(1) { it * 2 }
for (item in seq) {
println(item)
}
interface Sequence<out T> {
operator fun iterator(): Iterator<T>
}
interface Iterator<out T> {
operator fun next(): T
operator fun hasNext(): Boolean
}
val iter = seq.iterator()
while (iter.hasNext()) {
val item = iter.next()
println(item)
}
Sequence builders
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
fib.take(4).forEach { print("$it ") }
// Start 1 Next 1 Next 2 Next 3
fun <T> sequence(
block: suspend SequenceScope<T>.() ?> Unit
): Sequence<T>
abstract class SequenceScope<in T> {
abstract suspend fun yield(value: T)
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {
…
}
override fun hasNext(): Boolean {
…
}
override suspend fun yield(value: T) {
…
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {
State.NotReady ?> if (hasNext()) next() else error("oops")
State.Ready ?> {
state = State.NotReady
nextValue as T
}
else ?> error("oops")
}
override fun hasNext(): Boolean {
…
}
override suspend fun yield(value: T) {
…
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {}
override fun hasNext(): Boolean {
while (true) {
when (state) {
State.NotReady ?> {
state = State.Done
nextStep?!.resume(Unit)
}
State.Done ?> return false
State.Ready ?> return true
}
}
}
override suspend fun yield(value: T) {
…
}
}
interface Continuation<in T> {
val context: CoroutineContext
fun resumeWith(result: Result<T>)
}
fun <T> Continuation<T>.resume(value: T) =
resumeWith(Result.success(value))
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {}
override fun hasNext(): Boolean {
while (true) {
when (state) {
State.NotReady ?> {
state = State.Done
nextStep?!.resume(Unit)
}
State.Done ?> return false
State.Ready ?> return true
}
}
}
override suspend fun yield(value: T) {
…
}
}
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun hasNext(): Boolean {
…
}
override fun next(): T = when (state) {
…
}
override suspend fun yield(value: T) {
nextValue = value
state = State.Ready
}
}
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun hasNext(): Boolean {
…
}
override fun next(): T = when (state) {
…
}
override suspend fun yield(value: T) {
nextValue = value
state = State.Ready
return suspendCoroutineUninterceptedOrReturn { c ->
nextStep = c
COROUTINE_SUSPENDED
}
}
}
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
Continuation Passing Style
T | COROUTINE_SUSPENDED
suspend fun yield(value: T): Unit
source code
fun yield(value: T, cont: Continuation<Unit>): Any?
compiled code
Continuation Passing Style
override suspend fun yield(value: T) {
nextValue = value
state = State.Ready
return suspendCoroutineUninterceptedOrReturn { cont ->
nextStep = cont
COROUTINE_SUSPENDED
}
}
override suspend fun yield(value: T, cont: Continuation<Unit>): Any? {
nextValue = value
state = State.Ready
nextStep = cont
return COROUTINE_SUSPENDED
}
Dip into Coroutines - KTUG Munich 202303
Awesome Deep Recursion
Deeply recursive functions
fun depth(t: Tree?): Int =
if (t ?= null) 0 else maxOf(depth(t.left), depth(t.right)) + 1
println(depth(deepTree)) // StackOverflowError
class Tree(val left: Tree? = null, val right: Tree? = null)
val deepTree = generateSequence(Tree()) { Tree(left = it) }.take(100_000).last()
val depth = DeepRecursiveFunction<Tree?, Int> { t ->
if (t ?= null) 0 else maxOf(
callRecursive(t.left),
callRecursive(t.right)
) + 1
}
println(depth(deepTree)) // Ok
Deeply recursive functions
sealed class DeepRecursiveScope<T, R> {
abstract suspend fun callRecursive(value: T): R
}
override suspend fun callRecursive(value: T): R {
return suspendCoroutineUninterceptedOrReturn { c ->
this.cont = c as Continuation<Any?>
this.value = value
COROUTINE_SUSPENDED
}
}
fun runCallLoop(): R {
while (true) {
val result = this.result
val cont = this.cont
?: return result.getOrThrow()
if (UNDEFINED_RESULT ?= result) {
val r = try {
function(this, value, cont)
} catch (e: Throwable) {
cont.resumeWithException(e)
continue
}
if (r ??= COROUTINE_SUSPENDED)
cont.resume(r as R)
} else {
this.result = UNDEFINED_RESULT
cont.resumeWith(result)
}
}
}
Deeply recursive functions
sealed class DeepRecursiveScope<T, R> {
abstract suspend fun callRecursive(value: T): R
}
override suspend fun callRecursive(value: T): R {
return suspendCoroutineUninterceptedOrReturn { c ->
this.cont = c as Continuation<Any?>
this.value = value
COROUTINE_SUSPENDED
}
}
fun runCallLoop(): R {
while (true) {
val result = this.result
val cont = this.cont
?: return result.getOrThrow()
if (UNDEFINED_RESULT ?= result) {
val r = try {
function(this, value, cont)
} catch (e: Throwable) {
cont.resumeWithException(e)
continue
}
if (r ??= COROUTINE_SUSPENDED)
cont.resume(r as R)
} else {
this.result = UNDEFINED_RESULT
cont.resumeWith(result)
}
}
}
Dip into Coroutines - KTUG Munich 202303
Awesome Parser Combinators
Parsing expressions
sealed class Expr {
object TRUE : Expr()
object FALSE : Expr()
data class Var(val name: String) : Expr()
data class Not(val body: Expr) : Expr()
data class And(val left: Expr, val right: Expr) : Expr()
data class Or(val left: Expr, val right: Expr) : Expr()
data class Impl(val left: Expr, val right: Expr) : Expr()
}
val expr = "a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
object BooleanGrammar : Grammar<Expr>() {
init { register(regexToken("s+", ignored = true)) }
val tru by literalToken("true")
val fal by literalToken("false")
val id by regexToken("w+")
val lpar by literalToken("(")
val rpar by literalToken(")")
val not by literalToken("!")
val and by literalToken("&")
val or by literalToken("|")
val impl by literalToken("?>")
val negation by parser { -not * term() } map { Not(it) }
val braced by parser { -lpar * expr() * -rpar }
val term: Parser<Expr> by
(tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced
val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } }
val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } }
val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } }
val expr by implChain
override val root by expr
}
"a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
object BooleanGrammar : Grammar<Expr>() {
init { register(regexToken("s+", ignored = true)) }
val tru by literalToken("true")
val fal by literalToken("false")
val id by regexToken("w+")
val lpar by literalToken("(")
val rpar by literalToken(")")
val not by literalToken("!")
val and by literalToken("&")
val or by literalToken("|")
val impl by literalToken("?>")
val negation by parser { -not * term() } map { Not(it) }
val braced by parser { -lpar * expr() * -rpar }
val term: Parser<Expr> by
(tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced
val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } }
val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } }
val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } }
val expr by implChain
override val root by expr
}
suspend fun <T : Any, S : Any> ParsingScope.leftAssociative(
term: Parser<T>,
operator: Parser<S>,
transform: (T, S, T) ?> T
): T {
var l: T = term()
while (true) {
val (o, r) = maybe(parser { operator() to term() }) ?: break
l = transform(l, o, r)
}
return l
}
val input = "K | o | t | l | i | n | i | s | a | w | e | s | o | m | e"
parser { leftAssociative(id, "|") { l, _, r -> "$l$r" } }
https://github.com/alllex/parsus
Awesome Arrow Kt
https://arrow-kt.io/
Awesome! How to learn more?
More watching
More reading
https://kotlinlang.org/docs/coroutines-guide.html https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md
More tinkering
Than you!
Twitter @alllexist — GitHub @alllex

More Related Content

PPTX
Concurrent Application Development using Scala
PDF
Monadologie
PDF
Kotlin : Advanced Tricks - Ubiratan Soares
PPTX
Kotlin collections
PDF
Coroutines in Kotlin. In-depth review
PDF
Coroutines in Kotlin. UA Mobile 2017.
PDF
Pooya Khaloo Presentation on IWMC 2015
PDF
A swift introduction to Swift
Concurrent Application Development using Scala
Monadologie
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin collections
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. UA Mobile 2017.
Pooya Khaloo Presentation on IWMC 2015
A swift introduction to Swift

Similar to Dip into Coroutines - KTUG Munich 202303 (20)

PDF
VTU Data Structures Lab Manual
PDF
Simpler java
PPT
SDC - Einführung in Scala
PDF
Go: It's Not Just For Google
ODP
Scala 2 + 2 > 4
PDF
Functional Programming with Groovy
PDF
Kotlin Advanced - Apalon Kotlin Sprint Part 3
PDF
Atomically { Delete Your Actors }
PDF
I wrote the following change it to having a header, main and cpp fi.pdf
DOCX
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
PDF
Kotlinify Your Project!
PDF
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
PDF
3 kotlin vs. java- what kotlin has that java does not
PDF
Shapes and calculate (area and contour) / C++ oop concept
PDF
Deep dive into Coroutines on JVM @ KotlinConf 2017
PDF
Implement the following sorting algorithms Bubble Sort Insertion S.pdf
PDF
Kotlin coroutine - behind the scenes
PPTX
Scala - where objects and functions meet
VTU Data Structures Lab Manual
Simpler java
SDC - Einführung in Scala
Go: It's Not Just For Google
Scala 2 + 2 > 4
Functional Programming with Groovy
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Atomically { Delete Your Actors }
I wrote the following change it to having a header, main and cpp fi.pdf
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
Kotlinify Your Project!
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
3 kotlin vs. java- what kotlin has that java does not
Shapes and calculate (area and contour) / C++ oop concept
Deep dive into Coroutines on JVM @ KotlinConf 2017
Implement the following sorting algorithms Bubble Sort Insertion S.pdf
Kotlin coroutine - behind the scenes
Scala - where objects and functions meet
Ad

Recently uploaded (20)

PDF
Cost to Outsource Software Development in 2025
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PDF
Wondershare Recoverit Full Crack New Version (Latest 2025)
DOCX
How to Use SharePoint as an ISO-Compliant Document Management System
PPTX
Weekly report ppt - harsh dattuprasad patel.pptx
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PDF
MCP Security Tutorial - Beginner to Advanced
PPTX
CNN LeNet5 Architecture: Neural Networks
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
iTop VPN Crack Latest Version Full Key 2025
PPTX
GSA Content Generator Crack (2025 Latest)
PDF
Topaz Photo AI Crack New Download (Latest 2025)
PPTX
Tech Workshop Escape Room Tech Workshop
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
PDF
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
PPTX
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Cost to Outsource Software Development in 2025
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
Wondershare Recoverit Full Crack New Version (Latest 2025)
How to Use SharePoint as an ISO-Compliant Document Management System
Weekly report ppt - harsh dattuprasad patel.pptx
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
MCP Security Tutorial - Beginner to Advanced
CNN LeNet5 Architecture: Neural Networks
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
iTop VPN Crack Latest Version Full Key 2025
GSA Content Generator Crack (2025 Latest)
Topaz Photo AI Crack New Download (Latest 2025)
Tech Workshop Escape Room Tech Workshop
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
Autodesk AutoCAD Crack Free Download 2025
The Dynamic Duo Transforming Financial Accounting Systems Through Modern Expe...
Log360_SIEM_Solutions Overview PPT_Feb 2020.pptx
Ad

Dip into Coroutines - KTUG Munich 202303

  • 1. Dip into Coroutines A story full of suspends
  • 2. Software Engineer @ Gradle Formerly @ dxFeed Twitter @alllexist — GitHub @alllex Alex Semin
  • 4. fun main() = runBlocking { val jobs: List<Deferred<Boolean?> = List(100_000) { async { request(it) } } val evenCount = jobs.count { it.await() } println("There $evenCount even numbers") } suspend fun request(id: Int): Boolean { delay(1.seconds) return id % 2 ?= 0 }
  • 5. fun main() = runBlocking { val jobs: List<Deferred<Boolean?> = List(100_000) { async { request(it) } } val evenCount = jobs.count { it.await() } println("There $evenCount even numbers") } suspend fun request(id: Int): Boolean { delay(1.seconds) return id % 2 ?= 0 }
  • 6. fun main() = runBlocking { val jobs: List<Deferred<Boolean?> = List(100_000) { async { request(it) } } val evenCount = jobs.count { it.await() } println("There $evenCount even numbers") } suspend fun request(id: Int): Boolean { delay(1.seconds) return id % 2 ?= 0 } import kotlinx.coroutines.*
  • 7. What’s where? kotlinx.coroutines kotlin.coroutines launch async await … Job runBlocking coroutineScope Deferred withTimeout Continuation CoroutineContext createCoroutine* suspendCoroutine* COROUTINE_SUSPENDED ContinuationInterceptor delay … …
  • 9. Sequences list.asSequence() .filter { … } .map { … } .filter { … } // 1, 2, 4, 8, //. val seq = generateSequence(1) { it * 2 } for (item in seq) { println(item) } interface Sequence<out T> { operator fun iterator(): Iterator<T> } interface Iterator<out T> { operator fun next(): T operator fun hasNext(): Boolean } val iter = seq.iterator() while (iter.hasNext()) { val item = iter.next() println(item) }
  • 10. Sequence builders val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } } fib.take(4).forEach { print("$it ") } // Start 1 Next 1 Next 2 Next 3 fun <T> sequence( block: suspend SequenceScope<T>.() ?> Unit ): Sequence<T> abstract class SequenceScope<in T> { abstract suspend fun yield(value: T) }
  • 11. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) { … } override fun hasNext(): Boolean { … } override suspend fun yield(value: T) { … } }
  • 12. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) { State.NotReady ?> if (hasNext()) next() else error("oops") State.Ready ?> { state = State.NotReady nextValue as T } else ?> error("oops") } override fun hasNext(): Boolean { … } override suspend fun yield(value: T) { … } }
  • 13. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) {} override fun hasNext(): Boolean { while (true) { when (state) { State.NotReady ?> { state = State.Done nextStep?!.resume(Unit) } State.Done ?> return false State.Ready ?> return true } } } override suspend fun yield(value: T) { … } } interface Continuation<in T> { val context: CoroutineContext fun resumeWith(result: Result<T>) } fun <T> Continuation<T>.resume(value: T) = resumeWith(Result.success(value))
  • 14. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) {} override fun hasNext(): Boolean { while (true) { when (state) { State.NotReady ?> { state = State.Done nextStep?!.resume(Unit) } State.Done ?> return false State.Ready ?> return true } } } override suspend fun yield(value: T) { … } } val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } }
  • 15. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun hasNext(): Boolean { … } override fun next(): T = when (state) { … } override suspend fun yield(value: T) { nextValue = value state = State.Ready } } val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } }
  • 16. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun hasNext(): Boolean { … } override fun next(): T = when (state) { … } override suspend fun yield(value: T) { nextValue = value state = State.Ready return suspendCoroutineUninterceptedOrReturn { c -> nextStep = c COROUTINE_SUSPENDED } } } val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } }
  • 17. Continuation Passing Style T | COROUTINE_SUSPENDED suspend fun yield(value: T): Unit source code fun yield(value: T, cont: Continuation<Unit>): Any? compiled code
  • 18. Continuation Passing Style override suspend fun yield(value: T) { nextValue = value state = State.Ready return suspendCoroutineUninterceptedOrReturn { cont -> nextStep = cont COROUTINE_SUSPENDED } } override suspend fun yield(value: T, cont: Continuation<Unit>): Any? { nextValue = value state = State.Ready nextStep = cont return COROUTINE_SUSPENDED }
  • 21. Deeply recursive functions fun depth(t: Tree?): Int = if (t ?= null) 0 else maxOf(depth(t.left), depth(t.right)) + 1 println(depth(deepTree)) // StackOverflowError class Tree(val left: Tree? = null, val right: Tree? = null) val deepTree = generateSequence(Tree()) { Tree(left = it) }.take(100_000).last() val depth = DeepRecursiveFunction<Tree?, Int> { t -> if (t ?= null) 0 else maxOf( callRecursive(t.left), callRecursive(t.right) ) + 1 } println(depth(deepTree)) // Ok
  • 22. Deeply recursive functions sealed class DeepRecursiveScope<T, R> { abstract suspend fun callRecursive(value: T): R } override suspend fun callRecursive(value: T): R { return suspendCoroutineUninterceptedOrReturn { c -> this.cont = c as Continuation<Any?> this.value = value COROUTINE_SUSPENDED } } fun runCallLoop(): R { while (true) { val result = this.result val cont = this.cont ?: return result.getOrThrow() if (UNDEFINED_RESULT ?= result) { val r = try { function(this, value, cont) } catch (e: Throwable) { cont.resumeWithException(e) continue } if (r ??= COROUTINE_SUSPENDED) cont.resume(r as R) } else { this.result = UNDEFINED_RESULT cont.resumeWith(result) } } }
  • 23. Deeply recursive functions sealed class DeepRecursiveScope<T, R> { abstract suspend fun callRecursive(value: T): R } override suspend fun callRecursive(value: T): R { return suspendCoroutineUninterceptedOrReturn { c -> this.cont = c as Continuation<Any?> this.value = value COROUTINE_SUSPENDED } } fun runCallLoop(): R { while (true) { val result = this.result val cont = this.cont ?: return result.getOrThrow() if (UNDEFINED_RESULT ?= result) { val r = try { function(this, value, cont) } catch (e: Throwable) { cont.resumeWithException(e) continue } if (r ??= COROUTINE_SUSPENDED) cont.resume(r as R) } else { this.result = UNDEFINED_RESULT cont.resumeWith(result) } } }
  • 26. Parsing expressions sealed class Expr { object TRUE : Expr() object FALSE : Expr() data class Var(val name: String) : Expr() data class Not(val body: Expr) : Expr() data class And(val left: Expr, val right: Expr) : Expr() data class Or(val left: Expr, val right: Expr) : Expr() data class Impl(val left: Expr, val right: Expr) : Expr() } val expr = "a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
  • 27. object BooleanGrammar : Grammar<Expr>() { init { register(regexToken("s+", ignored = true)) } val tru by literalToken("true") val fal by literalToken("false") val id by regexToken("w+") val lpar by literalToken("(") val rpar by literalToken(")") val not by literalToken("!") val and by literalToken("&") val or by literalToken("|") val impl by literalToken("?>") val negation by parser { -not * term() } map { Not(it) } val braced by parser { -lpar * expr() * -rpar } val term: Parser<Expr> by (tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } } val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } } val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } } val expr by implChain override val root by expr } "a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
  • 28. object BooleanGrammar : Grammar<Expr>() { init { register(regexToken("s+", ignored = true)) } val tru by literalToken("true") val fal by literalToken("false") val id by regexToken("w+") val lpar by literalToken("(") val rpar by literalToken(")") val not by literalToken("!") val and by literalToken("&") val or by literalToken("|") val impl by literalToken("?>") val negation by parser { -not * term() } map { Not(it) } val braced by parser { -lpar * expr() * -rpar } val term: Parser<Expr> by (tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } } val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } } val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } } val expr by implChain override val root by expr }
  • 29. suspend fun <T : Any, S : Any> ParsingScope.leftAssociative( term: Parser<T>, operator: Parser<S>, transform: (T, S, T) ?> T ): T { var l: T = term() while (true) { val (o, r) = maybe(parser { operator() to term() }) ?: break l = transform(l, o, r) } return l } val input = "K | o | t | l | i | n | i | s | a | w | e | s | o | m | e" parser { leftAssociative(id, "|") { l, _, r -> "$l$r" } }
  • 32. Awesome! How to learn more?
  • 36. Than you! Twitter @alllexist — GitHub @alllex