Update 2025-03-27

This commit is contained in:
Alexander Nozik 2025-03-27 12:03:42 +03:00
parent 3fee214bc9
commit 8902de6a56
17 changed files with 846 additions and 327 deletions

View File

@ -1,6 +1,7 @@
plugins{
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.ktor)
`maven-publish`
}
group = "center.sciprog.demo"
@ -25,12 +26,12 @@ dependencies {
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.server.websockets)
implementation(libs.ktor.server.html.builder)
implementation(libs.ktor.server.call.logging)
implementation(libs.ktor.server.cors)
implementation(libs.ktor.server.host.common)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.cio)
@ -43,4 +44,4 @@ dependencies {
testImplementation(libs.ktor.server.test.host)
testImplementation(libs.kotlin.test.junit)
}
}

View File

@ -119,6 +119,7 @@
"val number = 1\n",
"\n",
"fun increment(num: Int) = num + 1\n",
"\n",
"println(\"This is an $arg string number ${increment(number) + 1}\")"
],
"metadata": {
@ -154,6 +155,13 @@
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "println(\"slash: \\\\\")",
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"source": [
@ -165,7 +173,7 @@
" line\n",
" raw\n",
" string\n",
"\"\"\".trimIndent()\n",
" \"\"\".trimIndent()\n",
")"
],
"metadata": {
@ -278,8 +286,9 @@
{
"cell_type": "code",
"source": [
"val intArray: IntArray = IntArray(21) { it -> it + 1 }\n",
"intArray.sum()"
"val array = DoubleArray(21) { it + 1.0 }\n",
"println(array.contentToString())\n",
"array.sum()"
],
"metadata": {
"datalore": {
@ -396,8 +405,13 @@
{
"cell_type": "code",
"source": [
"val base = \"base\"\n",
"\n",
"fun String.doSomethingInside() {\n",
" println(\"I did $base inside another function on $this\")\n",
"}\n",
"\n",
"fun doSomethingSpecial() {\n",
" val base = \"base\"\n",
" val special = \"special\"\n",
"\n",
" /**\n",
@ -408,7 +422,7 @@
" }\n",
" base.doSomethingInside()\n",
"}\n",
"//\"ddd\".doSomethingInside()\n",
"\"ddd\".doSomethingInside()\n",
"\n",
"doSomethingSpecial()"
],
@ -430,6 +444,13 @@
{
"cell_type": "code",
"source": [
"//object Converter{\n",
"// fun printStringWithPrefix(str: String) {\n",
"// println(\"Prefixed: $str\")\n",
"// }\n",
"//}\n",
"\n",
"\n",
"fun returnFunction(): (String) -> Unit {\n",
" fun printStringWithPrefix(str: String) {\n",
" println(\"Prefixed: $str\")\n",
@ -606,7 +627,7 @@
"}\n",
"\n",
"//@JvmOverloads\n",
"@JvmName(\"functionWithDefaultParameters\")\n",
"//@JvmName(\"functionWithDefaultParameters\")\n",
"fun functionWithParameters(a: Int = 2) { // don't do that\n",
" println(\"with default\")\n",
"}\n",
@ -616,6 +637,18 @@
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"fun fun1(a: Double = 2.0){TODO()}\n",
"fun fun1(a: Int = 2){TODO()}\n",
"\n",
"fun1()"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
@ -636,10 +669,24 @@
"source": [
"fun theSameAsBefore(a: Int = 0, b: String = \"\"): String = \"A string with a == $a and b == $b\"\n",
"\n",
"enum class Letters {\n",
" A, B, C\n",
"}\n",
"\n",
"fun funWithNumbers(letter: Letters): Unit = when (letter) {\n",
" Letters.A -> println(\"a\")\n",
" Letters.B -> println(\"b\")\n",
" Letters.C -> println(\"c\")\n",
"}\n",
"\n",
"class Context(val a: String, val b: String)\n",
"\n",
"fun somethingWith(context: Context) = with(context) {\n",
" println(a + b)\n",
"fun somethingWithout(context: Context): String {\n",
" return context.a + context.b\n",
"}\n",
"\n",
"fun somethingWith(context: Context): String = with(context) {\n",
" a + b\n",
"}"
],
"metadata": {
@ -762,6 +809,7 @@
" * A singleton (object) is a type (class) which have only one instance\n",
" */\n",
"object AnObject : AnInterface {\n",
" override val a by lazy { 4 }\n",
" override fun doSomething(): Unit = TODO(\"Not yet implemented\")\n",
"}\n",
"\n",
@ -787,14 +835,17 @@
" println(\"Do something\")\n",
"}\n",
"\n",
"/**\n",
" * The one that should not be named\n",
" */\n",
"val voldemort = object {\n",
" fun doSomething(): Unit = TODO()\n",
"}\n",
"\n",
"// voldemort.doSomething()"
"fun somethingWithV() {\n",
" /**\n",
" * The one that should not be named\n",
" */\n",
" val voldemort = object {\n",
" fun doSomething(): Unit = TODO()\n",
" }\n",
"\n",
" voldemort.doSomething()\n",
"}"
],
"metadata": {
"datalore": {
@ -827,6 +878,8 @@
"\n",
"sin(PI / 2)\n",
"\n",
"sin(2.0)\n",
"\n",
"sin(doubleArrayOf(0.0, PI / 2))"
],
"outputs": [],
@ -852,6 +905,8 @@
{
"cell_type": "code",
"source": [
"import kotlinx.coroutines.flow.FlowCollector\n",
"\n",
"interface Producer<out T> {\n",
" fun produce(): T\n",
"}\n",
@ -877,198 +932,7 @@
},
{
"cell_type": "markdown",
"source": [
"## Return on when\n",
"https://kotlinlang.org/docs/idioms.html#return-on-when-statement"
],
"attachments": {},
"metadata": {
"datalore": {
"node_id": "YDCyDwHaw8LGUsRYGvgnRA",
"type": "MD",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
}
},
{
"cell_type": "code",
"source": [
"fun transform(color: String): Int = when (color) {\n",
" \"Red\" -> 0\n",
" \"Green\" -> 1\n",
" \"Blue\" -> 2\n",
" else -> throw IllegalArgumentException(\"Invalid color param value\")\n",
"}"
],
"metadata": {
"datalore": {
"node_id": "fCgUSk32WDSfR1GjIKa4tH",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "fun transformIf(flag: Boolean): Int = if (flag) 1 else 0 ",
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
"## Runtime type dispatch\n",
"\n",
"In Java it is called DOP (Data Oriented Programming).\n",
"\n",
"Also, sometimes (wrongly) called pattern matching."
],
"attachments": {},
"metadata": {
"datalore": {
"node_id": "GI03Lj2Li76ORUHS53nTIx",
"type": "MD",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
}
},
{
"cell_type": "code",
"source": [
"/**\n",
" * Matching by type\n",
" */\n",
"fun checkType(arg: Any): Unit = when (arg) {\n",
" is String -> println(\"I am a String. Length is ${arg.length}\")\n",
" is Int -> println(\"I am an Int.\")\n",
" is Double -> println(\"I am a Double\")\n",
" //2==2 -> println(\"Wat?\")\n",
" else -> println(\"I don't know who am I?\")\n",
"}\n",
"\n",
"fun checkType2(arg: Any): Unit = when {\n",
" arg is String -> println(\"I am a String\")\n",
" arg is Int -> println(\"I am an Int\")\n",
" arg is Double -> println(\"I am a Double\")\n",
" 2 == 2 -> println(\"Wat?\")\n",
" else -> println(\"I don't know who am I?\")\n",
"}\n",
"\n",
"checkType(true)"
],
"metadata": {
"datalore": {
"node_id": "tJXxwCbGkVrfybQ0WZBOtt",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
"## Try-catch expression\n",
"https://kotlinlang.org/docs/idioms.html#try-catch-expression"
],
"attachments": {},
"metadata": {
"datalore": {
"node_id": "f0bGwDoiIdt91b3tSeL1rn",
"type": "MD",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
}
},
{
"cell_type": "code",
"source": [
"fun tryCatch() {\n",
" val result: Int = try {\n",
" 22\n",
" } catch (e: ArithmeticException) {\n",
" throw IllegalStateException(e)\n",
" } finally {\n",
" println(\"finally\")\n",
" }\n",
"\n",
" // Working with result\n",
"}"
],
"metadata": {
"datalore": {
"node_id": "qT7cCbqiG1c4Agyc9qD5I3",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"source": [
"val res: Result<Int> = runCatching<Int> {\n",
" //error(\"Error happened\")\n",
" 4\n",
"}\n",
"\n",
"println(res.exceptionOrNull())\n",
"(res.getOrNull() ?: 0) + 1"
],
"metadata": {
"datalore": {
"node_id": "MslvYANHimu0ByBevtI4NY",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"source": [
"val dataFlow = sequence {\n",
" var i = 0\n",
" while (true) {\n",
" yield(i++)\n",
" }\n",
"}\n",
"\n",
"dataFlow.map {\n",
" runCatching {\n",
" if (it % 2 == 0) error(\"Even: $it\") else it\n",
" }\n",
"}.take(10).toList().joinToString(separator = \"\\n\")"
],
"metadata": {
"datalore": {
"node_id": "4B3Hw7znY3cEDxBmytUJCV",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
"## Nothing"
],
"source": "## Nothing",
"attachments": {},
"metadata": {
"datalore": {
@ -1134,6 +998,212 @@
"outputs": [],
"execution_count": null
},
{
"metadata": {
"datalore": {
"node_id": "YDCyDwHaw8LGUsRYGvgnRA",
"type": "MD",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "markdown",
"source": [
"## Return on when\n",
"https://kotlinlang.org/docs/idioms.html#return-on-when-statement"
]
},
{
"metadata": {
"datalore": {
"node_id": "fCgUSk32WDSfR1GjIKa4tH",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "code",
"source": [
"fun transform(color: String): Int = when (color) {\n",
" \"Red\" -> 0\n",
" \"Green\" -> 1\n",
" \"Blue\" -> 2\n",
" else -> throw IllegalArgumentException(\"Invalid color param value\")\n",
"}"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "fun transformIf(flag: Boolean): Int = if (flag) 1 else 0",
"outputs": [],
"execution_count": null
},
{
"metadata": {
"datalore": {
"node_id": "GI03Lj2Li76ORUHS53nTIx",
"type": "MD",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "markdown",
"source": [
"## Runtime type dispatch\n",
"\n",
"In Java it is called DOP (Data Oriented Programming).\n",
"\n",
"Also, sometimes (wrongly) called pattern matching."
]
},
{
"metadata": {
"datalore": {
"node_id": "tJXxwCbGkVrfybQ0WZBOtt",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "code",
"source": [
"/**\n",
" * Matching by type\n",
" */\n",
"fun checkType(arg: Any): Unit = when (arg) {\n",
" is String -> println(\"I am a String. Length is ${arg.length}\")\n",
" is Int -> println(\"I am an Int.\")\n",
" is Double -> println(\"I am a Double\")\n",
" //2==2 -> println(\"Wat?\")\n",
" else -> println(\"I don't know who am I?\")\n",
"}\n",
"\n",
"fun checkType2(arg: Any): Unit = when {\n",
" arg is String -> println(\"I am a String\")\n",
" arg is Int -> println(\"I am an Int\")\n",
" arg is Double -> println(\"I am a Double\")\n",
" 2 == 2 -> println(\"Wat?\")\n",
" else -> println(\"I don't know who am I?\")\n",
"}\n",
"\n",
"checkType(true)"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {
"datalore": {
"node_id": "f0bGwDoiIdt91b3tSeL1rn",
"type": "MD",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "markdown",
"source": [
"## Try-catch expression\n",
"https://kotlinlang.org/docs/idioms.html#try-catch-expression"
]
},
{
"metadata": {
"datalore": {
"node_id": "qT7cCbqiG1c4Agyc9qD5I3",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "code",
"source": [
"fun tryCatch() {\n",
" val result: Int = try {\n",
" 22\n",
" } catch (e: ArithmeticException) {\n",
" throw IllegalStateException(e)\n",
" } finally {\n",
" println(\"finally\")\n",
" }\n",
"\n",
" // Working with result\n",
"}"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {
"datalore": {
"node_id": "MslvYANHimu0ByBevtI4NY",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "code",
"source": [
"val res: Result<Int> = runCatching<Int> {\n",
" error(\"Error happened\")\n",
" 4\n",
"}\n",
"\n",
"println(res.exceptionOrNull())\n",
"(res.getOrNull() ?: 0) + 1"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"sealed interface MyResult<T>{\n",
" class OK<T>(val value: T):MyResult<T>\n",
" sealed interface Failure: MyResult<Nothing>\n",
" object NotFound: Failure\n",
" object InternalError: Failure\n",
"}\n",
"\n",
"fun evaluate(res: MyResult<Int>): Int = when(res){\n",
" is MyResult.OK -> res.value\n",
" is MyResult.NotFound -> error(\"not found\")\n",
" is MyResult.InternalError -> error(\"Unknown\")\n",
"}\n"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {
"datalore": {
"node_id": "4B3Hw7znY3cEDxBmytUJCV",
"type": "CODE",
"hide_input_from_viewers": true,
"hide_output_from_viewers": true
}
},
"cell_type": "code",
"source": [
"val dataFlow = sequence {\n",
" var i = 0\n",
" while (true) {\n",
" yield(i++)\n",
" }\n",
"}\n",
"\n",
"dataFlow.map {\n",
" runCatching {\n",
" if (it % 2 == 0) error(\"Even: $it\") else it\n",
" }\n",
"}.take(10).toList().joinToString(separator = \"\\n\")"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
@ -1246,7 +1316,7 @@
"\n",
"println(typeOf<Optional<Boolean>>() == typeOf<Optional<Optional<Boolean>>>())\n",
"\n",
"println(typeOf<Boolean?>() == typeOf<Boolean??>())"
"println(typeOf<Boolean?>() == typeOf<Boolean????>())"
],
"outputs": [],
"execution_count": null
@ -1254,7 +1324,10 @@
{
"metadata": {},
"cell_type": "code",
"source": "mapOf<String, String>().get(\"f\")!!",
"source": [
"mapOf<String, String>().get(\"f\")!!\n",
"//mapOf<String, String>().get(\"f\") ?: error(\"Undefinded f\")"
],
"outputs": [],
"execution_count": null
},
@ -1281,11 +1354,8 @@
"/**\n",
" * Safe call and elvis operator\n",
" */\n",
"fun idiom12() {\n",
" val files = File(\"Test\").listFiles()\n",
" println(files?.size ?: \"empty\")\n",
"}\n",
"idiom12()"
"val files = File(\"Test\").listFiles()\n",
"println(files?.size ?: \"empty\")\n"
],
"metadata": {
"datalore": {
@ -1309,6 +1379,8 @@
"//val value: Int? by lazy { 2 }\n",
"\n",
"//printNotNull(value) // Error\n",
"\n",
"// smart cast\n",
"if (value != null) {\n",
" //not guaranteed to work with mutable variable\n",
" printNotNull(value)\n",
@ -1418,6 +1490,17 @@
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"fun Nothing.printNothing() = println(\"Nothing!\")\n",
"\n",
"error(\"!\").printNothing()"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"source": [
@ -1481,6 +1564,10 @@
" println(get(arg))\n",
"}\n",
"\n",
"fun List<String>.topLevelFunctionWithReciever(arg: Int): Unit {\n",
" println(get(arg))\n",
"}\n",
"\n",
"listOf(\"1\", \"2\", \"3\").functionWithReciever(1)"
],
"outputs": [],
@ -1564,6 +1651,9 @@
{
"cell_type": "code",
"source": [
"import kotlinx.coroutines.CoroutineScope\n",
"import kotlinx.datetime.Instant\n",
"\n",
"/**\n",
" * Extension variable (also must be virtual)\n",
" */\n",
@ -1573,7 +1663,6 @@
" this[1] = value\n",
" }\n",
"\n",
"\n",
"val array = Array(5) { it }\n",
"array.second = 9\n",
"array"
@ -1653,7 +1742,9 @@
"\n",
"fun printAbc(aClass: AClass) = with(AContext) {\n",
" aClass.abc()\n",
"}"
"}\n",
"\n",
"printAbc(getAClass()!!)"
],
"outputs": [],
"execution_count": null
@ -1669,7 +1760,7 @@
"}\n",
"\n",
"val runResult: Int = run {\n",
"\n",
" 2\n",
"}\n",
"\n",
"//Using `let` to compose result. Not recommended using without a need\n",
@ -1734,7 +1825,7 @@
" */\n",
"fun getAndIncrement() = i.also { i += 1 } //don't do that\n",
"\n",
"fun incrementAndPring(arg: Int) = (arg + 1).also{\n",
"fun incrementAndPring(arg: Int) = (arg + 1).also {\n",
" println(it)\n",
"}\n",
"\n",
@ -1908,6 +1999,7 @@
"fun consumeList(list: List<Int>) {\n",
" println(list.joinToString())\n",
"}\n",
"\n",
"consumeList(mutableList)\n",
"mutableList.add(4)\n",
"consumeList(mutableList)"
@ -2087,7 +2179,13 @@
{
"cell_type": "code",
"source": [
"val map = mutableMapOf(\n",
"val roMap: Map<String, String> = mapOf(\n",
" \"key\" to \"a\",\n",
" \"key2\" to \"b\",\n",
")\n",
"\n",
"\n",
"val map: MutableMap<String, String> = mutableMapOf(\n",
" \"key\" to \"a\",\n",
" \"key2\" to \"b\",\n",
")\n",
@ -2438,7 +2536,7 @@
" //.asSequence()\n",
" .filter { it % 2 == 0 } //select even numbers\n",
" .map { it * it } // get square of each element\n",
" //.onEach { println(it) }\n",
"// .onEach { println(it) }\n",
" //.sumOf { it } //use one of reduce operations\n",
" .reduce { acc: Int, i: Int -> acc + i }\n",
" //.fold(0.0) { acc: Double, i: Int -> acc + i }\n",
@ -2780,7 +2878,7 @@
" */\n",
"fun foo(): Int {\n",
" listOf(1, 2, 3, 4, 5).forEachOdd {\n",
" if (it == 3) return it // non-local return directly to the caller of foo()\n",
" if (it == 3) return@foo it // non-local return directly to the caller of foo()\n",
" print(\"$it, \")\n",
" }\n",
" println(\"this point is unreachable\")\n",

View File

@ -101,6 +101,29 @@
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"interface AClass {\n",
" fun interface Factory {\n",
" fun create(): AClass\n",
" }\n",
"}\n",
"\n",
"fun createAClass(factory: AClass.Factory): AClass{\n",
" return factory.create()\n",
"}\n",
"\n",
"class BClass : AClass {\n",
" companion object : AClass.Factory {\n",
" override fun create(): AClass = BClass()\n",
" }\n",
"}"
],
"outputs": [],
"execution_count": null
},
{
"cell_type": "code",
"source": [
@ -151,9 +174,7 @@
},
{
"cell_type": "code",
"source": [
"createWithAWord(\"Hello\"){body -> B(\">\\t$body\")}"
],
"source": "createWithAWord(\"Hello\"){ body -> B(\">\\t$body\")}",
"metadata": {
"datalore": {
"node_id": "TvX8qzziDGxZWf044iqHO3",
@ -272,14 +293,14 @@
{
"cell_type": "code",
"source": [
"class WithLazy{\n",
"class WithLazy {\n",
" val prop = 2\n",
" get(){\n",
" get() {\n",
" println(\"Hit $field\")\n",
" return field\n",
" }\n",
"\n",
" val lazyProp by lazy{\n",
" val lazyProp by lazy {\n",
" println(\"Hit lazy\")\n",
" 2\n",
" }\n",
@ -398,9 +419,7 @@
},
{
"cell_type": "code",
"source": [
"Buildable(b = 5)"
],
"source": "Buildable(b = 5)",
"metadata": {
"datalore": {
"node_id": "EQoUX3r984KJvt9tkpy3Wd",
@ -434,9 +453,9 @@
{
"cell_type": "code",
"source": [
"fun Buildable(block: Buildable.()-> Unit): Buildable = Buildable().apply(block)\n",
"fun Buildable(block: Buildable.() -> Unit): Buildable = Buildable().apply(block)\n",
"\n",
"Buildable{ \n",
"Buildable {\n",
" a = 1\n",
" setABC(a + b + c)\n",
"}"
@ -470,15 +489,15 @@
{
"cell_type": "code",
"source": [
"class Multiton private constructor(val name: String){\n",
" init{\n",
"class Multiton private constructor(val name: String) {\n",
" init {\n",
" println(\"Multiton $name created\")\n",
" }\n",
" \n",
"\n",
" companion object {\n",
" private val cache = HashMap<String, Multiton>()\n",
"\n",
" fun resolve(name: String) = cache.getOrPut(name){Multiton(name)}\n",
" fun resolve(name: String) = cache.getOrPut(name) { Multiton(name) }\n",
" }\n",
"}"
],
@ -531,15 +550,15 @@
{
"cell_type": "code",
"source": [
"sealed interface SealedMultiton{\n",
" object A: SealedMultiton\n",
" object B: SealedMultiton\n",
" class Custom(val body: String): SealedMultiton\n",
"sealed interface SealedMultiton {\n",
" object A : SealedMultiton\n",
" object B : SealedMultiton\n",
" class Custom(val body: String) : SealedMultiton\n",
"}\n",
"\n",
"fun evaluateSealedMultiton(sealed: SealedMultiton) = when(sealed){\n",
" is SealedMultiton.A-> println(\"A\")\n",
" is SealedMultiton.B-> println(\"B\")\n",
"fun evaluateSealedMultiton(sealed: SealedMultiton) = when (sealed) {\n",
" is SealedMultiton.A -> println(\"A\")\n",
" is SealedMultiton.B -> println(\"B\")\n",
" is SealedMultiton.Custom -> println(sealed.body)\n",
"}"
],
@ -572,15 +591,14 @@
{
"cell_type": "code",
"source": [
"val array = doubleArrayOf(1.0,2.0)\n",
"val list = listOf(1.0,2.0)\n",
"val array = doubleArrayOf(1.0, 2.0)\n",
"val list = listOf(1.0, 2.0)\n",
"\n",
"\n",
"fun consumeList(l: List<Double>){\n",
"fun consumeList(l: List<Double>) {\n",
" println(l)\n",
"}\n",
"\n",
"fun convertArrayToList(array: DoubleArray): List<Double> = array.asList()//List(array.size){i -> array[i]}\n",
"private fun convertArrayToList(array: DoubleArray): List<Double> = array.asList()//List(array.size){i -> array[i]}\n",
"\n",
"consumeList(convertArrayToList(array))"
],
@ -649,10 +667,10 @@
{
"cell_type": "code",
"source": [
"class ValueHolder{\n",
"open class ValueHolder {\n",
" var value = 2\n",
"\n",
" fun printValue(){\n",
" open fun printValue() {\n",
" println(value)\n",
" }\n",
"}\n",
@ -827,9 +845,9 @@
{
"cell_type": "code",
"source": [
"class StringProxy(val string: String): CharSequence by string{\n",
" override fun get(index: Int): Char{\n",
" return if(index < 0) '!' else string[index]\n",
"class StringProxy(val string: String) : CharSequence by string {\n",
" override fun get(index: Int): Char {\n",
" return if (index < 0) '!' else string[index]\n",
" }\n",
"}"
],
@ -975,22 +993,22 @@
{
"cell_type": "code",
"source": [
"fun interface StructureVisitor{\n",
"fun interface StructureVisitor {\n",
" fun visit(structure: Structure): Unit\n",
"}\n",
"\n",
"val myStructureVisitor = object: StructureVisitor{\n",
" override fun visit(structure: Structure){\n",
" when(structure){\n",
"val myStructureVisitor = object : StructureVisitor {\n",
" override fun visit(structure: Structure) {\n",
" when (structure) {\n",
" is StringStructure -> println(\"It is a StringStructure with value ${structure.string}\")\n",
" is IntStructure -> println(\"It is a IntStructure with value ${structure.int}\")\n",
" is StructureList -> structure.content.forEach{ visit(it) }\n",
" is StructureList -> structure.content.forEach { visit(it) }\n",
" else -> println(\"I don't know what it is\")\n",
" }\n",
" }\n",
"}\n",
"\n",
"fun StructureList.visit(visitor: StructureVisitor){\n",
"fun StructureList.visit(visitor: StructureVisitor) {\n",
" visitor.visit(this)\n",
"}"
],
@ -1093,12 +1111,12 @@
"source": [
"val sealedStructureList = listOf<SealedStructure>(\n",
" StringSealedStructure(\"ddd\"),\n",
" IntSealedStructure(2), \n",
" IntSealedStructure(2),\n",
" IntSealedStructure(7),\n",
")\n",
"\n",
"sealedStructureList.visit{ structure ->\n",
" when(structure){\n",
"sealedStructureList.visit { structure ->\n",
" when (structure) {\n",
" is StringSealedStructure -> println(\"It is a StringSealedStructure with value ${structure.string}\")\n",
" is IntSealedStructure -> println(\"It is a IntSealedStructure with value ${structure.int}\")\n",
" else -> {} // why is that?\n",

View File

@ -0,0 +1,213 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {
"collapsed": true
},
"source": "",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"\n",
"import java.net.InetSocketAddress\n",
"import java.net.ProxySelector\n",
"import java.net.http.HttpClient\n",
"import java.net.http.HttpClient.*\n",
"\n",
"val client: HttpClient = HttpClient.newBuilder()\n",
" .version(Version.HTTP_1_1)\n",
" .build()"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"import java.net.URI\n",
"import java.net.http.HttpRequest.BodyPublishers\n",
"import java.net.http.HttpRequest\n",
"import java.net.http.HttpResponse.BodyHandlers\n",
"\n",
"val request: HttpRequest = HttpRequest.newBuilder()\n",
" .uri(URI.create(\"https://mipt.ru/\"))\n",
"// .header(\"Content-Type\", \"application/json\")\n",
" .GET()\n",
" .build()\n",
"\n",
"val response = client.send(request, BodyHandlers.ofString())\n",
"println(response.statusCode())\n",
"println(response.body().take(200))"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "%use ktor-client",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "val ktorClient = io.ktor.client.HttpClient()",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"import io.ktor.client.plugins.timeout\n",
"import io.ktor.client.request.get\n",
"import io.ktor.client.statement.bodyAsText\n",
"import kotlinx.coroutines.runBlocking\n",
"\n",
"runBlocking {\n",
" val response = ktorClient.get(\"https://mipt.ru\")\n",
" println(response.bodyAsText().take(200))\n",
"}"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"USE {\n",
" val ktorVersion = \"3.0.1\"\n",
" dependencies{\n",
" implementation(\"io.ktor:ktor-server-core-jvm:$ktorVersion\")\n",
" implementation(\"io.ktor:ktor-server-cio-jvm:$ktorVersion\")\n",
" implementation(\"io.ktor:ktor-client-core:$ktorVersion\")\n",
" implementation(\"io.ktor:ktor-client-cio:$ktorVersion\")\n",
" implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1\")\n",
" }\n",
"}"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"import io.ktor.server.cio.CIO\n",
"import io.ktor.server.engine.embeddedServer\n",
"import io.ktor.server.request.receiveText\n",
"import io.ktor.server.response.respondText\n",
"import io.ktor.server.routing.Route\n",
"import io.ktor.server.routing.get\n",
"import io.ktor.server.routing.post\n",
"import io.ktor.server.routing.route\n",
"import io.ktor.server.routing.routing\n",
"import kotlinx.coroutines.sync.*\n",
"\n",
"fun Route.processData(){\n",
"\n",
" val state = mutableMapOf<String, String>()\n",
" val mutex = Mutex()\n",
"\n",
" get(\"{path}\") {\n",
" val parameter = call.pathParameters[\"path\"]\n",
" call.respondText(state[parameter] ?: \"null\")\n",
" }\n",
"\n",
" post(\"{path}\") {\n",
" val parameter = call.pathParameters[\"path\"] ?: error(\"!\")\n",
" mutex.withLock {\n",
" state[parameter] = call.receiveText()\n",
" }\n",
" call.respondText(\"OK\")\n",
" }\n",
"}\n",
"\n",
"\n",
"val server = embeddedServer(CIO, port = 8080) {\n",
"\n",
"\n",
" routing {\n",
" get(\"/\") {\n",
" call.respondText(\"Hello MIPT!\")\n",
" }\n",
"\n",
" route(\"/data\"){\n",
" processData()\n",
" }\n",
" }\n",
"}.start()"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "server.stop()",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"import io.ktor.client.HttpClient\n",
"\n",
"val ktorClient: HttpClient = HttpClient()"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"import kotlinx.coroutines.*\n",
"\n",
"runBlocking {\n",
" val response = ktorClient.get(\"http://localhost\")\n",
" println(response.bodyAsText())\n",
"}"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "",
"outputs": [],
"execution_count": null
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.9.23",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
},
"ktnbPluginMetadata": {
"projectLibraries": false
}
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -6,6 +6,7 @@ import io.ktor.websocket.readText
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.time.Instant
@ -21,6 +22,7 @@ suspend fun CoroutineScope.aggregateFromService(url: String): List<Instant> {
launch {
client.webSocket(url) {
outgoing.send(Frame.Text("Connected"))
// delay(500)
val res = incoming.receiveAsFlow()
.filterIsInstance<Frame.Text>()
.take(3)

View File

@ -1,7 +1,6 @@
package examples
import kotlinx.coroutines.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.coroutines.CoroutineContext
@ -19,8 +18,7 @@ class ApplicationWithScope(
}
}
fun ApplicationWithScope.launchJob() = launch { }
fun ApplicationWithScope.launchJob() = launch { }
fun ApplicationWithScope(){
CoroutineScope(Dispatchers.Default)
}
fun ApplicationWithScope() =
ApplicationWithScope(Dispatchers.Default)

View File

@ -1,20 +1,25 @@
package examples
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
private fun doSomethingBlocking(){
runBlocking {
println("Blocking")
delay(10000)
}
}
fun main() {
runBlocking {
withContext(Dispatchers.Default) {
doSomethingBlocking()
repeat(20) {
launch(Dispatchers.Default) {
doSomethingBlocking()
}
}
}
}

View File

@ -0,0 +1,28 @@
package examples
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.newSingleThreadContext
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis
private suspend fun somethingAsync(res: String): String {
delay(200)
return res
}
suspend fun main(): Unit {
measureTimeMillis {
GlobalScope.launch(newSingleThreadContext("main")) {
println(coroutineContext)
launch {
println(somethingAsync("some string"))
}
launch {
println(somethingAsync("some string"))
}
}.join()
}.also { println(it) }
}

View File

@ -5,11 +5,11 @@ import kotlinx.coroutines.*
suspend fun main(): Unit = coroutineScope {
val masterJob = launch(
// CoroutineExceptionHandler { coroutineContext, throwable ->
// println(throwable)
// }
CoroutineExceptionHandler { coroutineContext, throwable ->
println(throwable)
}
) {
coroutineScope {
supervisorScope {
val subJob = launch {
// println(coroutineContext[Job])
delay(100)
@ -17,18 +17,22 @@ suspend fun main(): Unit = coroutineScope {
error("BOOM!")
}
}
val subDeferred = async {
delay(200)
println("Task completed")
"Completed"
}
// delay(50)
// cancel()
// subJob.await()
println(subDeferred.await())
}
}
// delay(50)
// masterJob.cancel()
masterJob.join()
println("Master job joined")
}

View File

@ -0,0 +1,49 @@
package examples
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.isActive
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
fun <K, V> Flow<Map<K, V>>.combine(
duration: Duration,
): Flow<Map<K, V>> = flow {
val collector = HashMap<K, V>()
val mutex = Mutex()
coroutineScope {
onEach { value ->
mutex.withLock {
collector.putAll(value)
}
}.launchIn(this)
while (isActive) {
delay(duration)
mutex.withLock {
emit(collector)
collector.clear()
}
}
}
}
suspend fun main(): Unit = coroutineScope {
val generator = flow {
var counter = 0
while (true) {
delay(10)
emit(mapOf(counter to counter))
counter++
}
}
generator.combine(100.milliseconds).take(10).onEach { println(it) }.launchIn(this)
}

View File

@ -3,20 +3,23 @@ package examples
import kotlinx.coroutines.*
suspend fun main() = withContext(Dispatchers.Unconfined) {
suspend fun main() = coroutineScope {
println(currentCoroutineContext())
val job1: Job = launch {
delay(200)
delay(300)
println("Job1 completed")
}
val deferred1: Deferred<String> = async {
delay(200)
println("deferred1 completed")
return@async "Complete"
}
val job2 = launch {
val job2 = launch(Dispatchers.Default + CoroutineName("Job2")) {
delay(100)
job1.cancel()
println("Job1 canceled")

View File

@ -0,0 +1,53 @@
package examples
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class StateInCoroutine {
val collection = mutableListOf<String>()
private val mutex = Mutex()
suspend fun mutateInTransaction(block: suspend MutableList<String>.() -> Unit): Unit {
mutex.withLock {
collection.block()
}
}
}
fun CoroutineScope.mutate(
state: StateInCoroutine,
block: suspend MutableList<String>.() -> Unit
) = launch {
state.mutateInTransaction(block)
}
suspend fun main(): Unit = coroutineScope {
val state = StateInCoroutine()
val job1 = mutate(state) {
delay(1)
repeat(10) {
delay(1)
add(it.toString())
}
}
val job2 = mutate(state) {
repeat(10) {
delay(1)
add("~$it")
}
}
job1.join()
job2.join()
println(state.collection)
}

View File

@ -0,0 +1,14 @@
package examples
import kotlinx.coroutines.delay
fun generate() = sequence {
while (true) {
yield(1)
yield(2)
}
}
fun main() {
generate().take(10).forEach { println(it) }
}

View File

@ -0,0 +1,33 @@
package examples
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.math.BigDecimal
suspend fun main(): Unit = coroutineScope {
val sharedFlow = MutableSharedFlow<String>()
sharedFlow.take(20).onEach {
delay(10)
println("1:$it")
}.launchIn(this)
sharedFlow.take(20).onEach {
delay(20)
println("2:$it")
}.launchIn(this)
launch {
var counter = 0
while (isActive) {
sharedFlow.emit("hello[${counter++}]")
}
}
}

View File

@ -3,7 +3,6 @@ package microservice
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
@ -18,10 +17,12 @@ fun CoroutineScope.launchPriceUpdateFlow(
db: PriceDB,
duration: Duration
): Job {
val dbChannel = Channel<Pair<Instant, BigDecimal>>()
val dbChannel = Channel<Pair<Instant, BigDecimal>>(1000)
dbChannel.consumeAsFlow().buffer(1000).onEach { (now, price) ->
db.storePrice(now, price)
dbChannel.consumeAsFlow().chunked(100).onEach { chunk ->
chunk.forEach { (now, price) ->
db.storePrice(now, price)
}
}.catch {
}.launchIn(this)
@ -36,6 +37,18 @@ fun CoroutineScope.launchPriceUpdateFlow(
// db.storePrice(now, price)
// }.launchIn(this)
val deque = ArrayDeque<Pair<Instant, BigDecimal>>()
// val dataChannel = Channel<Pair<Instant, BigDecimal>>(1000)
//
// launch {
// while (true) {
// delay(readDelay)
// val now = Clock.System.now()
// val price = reader.readPrice()
// dataChannel.send(now to price)
// }
// }
return flow<Pair<Instant, BigDecimal>> {
while (true) {
@ -47,8 +60,8 @@ fun CoroutineScope.launchPriceUpdateFlow(
}.flowOn(Dispatchers.IO).onEach { pair ->
//pricesFlow.emit(pair)
dbChannel.send(pair)
//db.storePrice(now, price)
}.runningFold(ArrayDeque<Pair<Instant, BigDecimal>>()) { deque, item ->
//db.storePrice(pair.first, pair.second)
}.map { item ->
deque.addFirst(item)
//TODO add cleanup
deque

View File

@ -6,86 +6,78 @@ import io.ktor.server.html.respondHtml
import io.ktor.server.request.receiveText
import io.ktor.server.response.respond
import io.ktor.server.response.respondText
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import io.ktor.server.routing.*
import io.ktor.server.websocket.WebSockets
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.launch
import kotlinx.coroutines.newFixedThreadPoolContext
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import kotlinx.coroutines.withContext
import kotlinx.html.body
import kotlinx.html.h1
import kotlin.coroutines.CoroutineContext
fun Route.subroute(key: String){
fun Route.subroute(key: String) {
var content = ""
get("get") {
call.respondText("Content[$key]: ${content}")
}
post("set"){
post("set") {
content = call.receiveText()
call.respond(HttpStatusCode.OK)
}
}
suspend fun executeQuery(queryName: String, ioContext: CoroutineContext = Dispatchers.IO): String{
withContext(ioContext){
Thread.sleep(1000)
suspend fun executeQuery(queryName: String, ioContext: CoroutineContext = Dispatchers.IO): String {
withContext(ioContext) {
Thread.sleep(10000)
//some blocking logic
}
return queryName
}
suspend fun main():Unit = coroutineScope{
fun main(): Unit {
embeddedServer(CIO, port = 8080, host = "localhost") {
install(WebSockets)
// install(CallLogging)
val ioContext = newFixedThreadPoolContext(12, "DB") //Dispatchers.IO
routing {
get("/") {
val callerName = call.queryParameters["name"] ?: "World"
// call.respondHtml {
// body{
// h1("Hello $callerName!")
// }
// }
call.respondText("Hello $callerName!")
call.respondHtml {
body {
h1("Hello $callerName!")
}
}
//call.respondText("Hello $callerName!")
}
get("/query/{queryName}"){
get("/query/{queryName}") {
val queryName = call.parameters["queryName"] ?: "query"
val queryResult = executeQuery(queryName, ioContext)
call.respondText("$queryName successful: $queryResult")
}
route("subroute"){
route("subroute") {
subroute("0")
}
route("subroute1"){
route("subroute1") {
subroute("1")
}
route("producer"){
route("producer") {
streamingModule()
}
get("aggregated"){
get("aggregated") {
val result = aggregateFromService("ws://localhost:8080/producer")
call.respondText(result.toString())
}
}
}.start()
}
}.start(true)
}

View File

@ -8,8 +8,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.time.Instant
import kotlin.time.Duration.Companion.microseconds
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@ -29,16 +27,13 @@ fun Route.streamingModule() {
println(frame)
}
}
repeat(3){
delay(100.milliseconds)
outgoing.send(Frame.Text(Instant.now().toString()))
}
// launch {
// while (isActive) {
// outgoing.send(Frame.Text(channel.receive().toString()))
// }
// }
while (isActive) {
val event = channel.receive()
println(event)
outgoing.send(Frame.Text(event.toString()))
}
}
}