2653 lines
63 KiB
Plaintext
2653 lines
63 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": "* Official list of idioms: https://kotlinlang.org/docs/idioms.html\n",
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "e5U9H2j8YPqeTklThKWtLy",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "xIF3Up82GVsiV1Ceze6Si3",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Preamble/Important notes\n",
|
||
"\n",
|
||
"* \"Syntactic sugar\" is a false concept. Each language feature affects how we use the language.\n",
|
||
"* One can adopt different programming styles in Kotlin. Idiomatic kotlin is an unofficial combination of practices developed by experienced Kotlin users.\n",
|
||
"* One of the key features of idiomatic kotlin is to use scopes instead of objects to provide incapsulation and limit visible mutable state.\n",
|
||
"\n",
|
||
"### What is idiomatic Kotlin (roughly)?\n",
|
||
"\n",
|
||
"* Less \"ceremony\". Pragmatic approach.\n",
|
||
"* Hybrid object/functional paradigm (objects for data, functions for interactions).\n",
|
||
"* Don't use mutable state wherever read-only is enough.\n",
|
||
"* Don't use classes when functions are enough.\n",
|
||
"* Don't use inheritance when composition is enough.\n",
|
||
"* Function is a first-class citizen.\n",
|
||
"* Scope is a first-class citizen.\n",
|
||
"* Use extensions to separate inner workings from utilities.\n",
|
||
"\n",
|
||
"### Do not do\n",
|
||
"\n",
|
||
"* Scope pollution.\n",
|
||
"* Scope function abuse.\n",
|
||
"* Rely on initialization order."
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "ARXeE5sXcjig7Oxpa5hdTG",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## String interpolation\n",
|
||
"\n",
|
||
"Interpolated string allows constructing string fast"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "LVICJjSl3FQ9CWiBWDaNlp",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "xIF3Up82GVsiV1Ceze6Si3",
|
||
"relativeY": 6
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"println(\"This is a plain string\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "FFW0GaV6uhemvZxlpnjpFL",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "ypTKLK2KvAZfnMbTgaVqNK",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val arg = \"Interpolated\"\n",
|
||
"println(\"This is an $arg string\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "ZsQ4OOCMRSSkquucGThKYh",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "qyGLHGsLl6mRCaOjpZBTD3",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val number = 1\n",
|
||
"\n",
|
||
"fun increment(num: Int) = num + 1\n",
|
||
"println(\"This is an $arg string number ${increment(number) + 1}\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "7V2Dsj0FwQaSqFJcYcWsz9",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "7tql3kbsQ9JIbbEfghi48B",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"println(\"This is a string with \\$\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "hm9iYlWj1B2S0469GtxDrf",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "BQz86nEWOj77fxXQ8iS47U",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"println(\"\"\"\n",
|
||
" This is a \n",
|
||
" multi\n",
|
||
" line\n",
|
||
" raw\n",
|
||
" string\n",
|
||
"\"\"\".trimIndent())"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "h6GsBoqNfrx3k1edy3hjKZ",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "RTl3zV3tStzlLoIHSvEZiV",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"println(\"\"\"This is a raw string number ${number+1} with \\ and ${'$'} \"\"\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "KDL3D9lOVn6vX3iTAY50gb",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "xmBQdVRhRGLsw0t87vxQW7",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Make `val`, not `var`!\n",
|
||
"\n",
|
||
"`val` means read-only property\n",
|
||
"\n",
|
||
"`var` means writable property\n",
|
||
"\n",
|
||
"Unnecessary use of `var` is not recommended.\n",
|
||
"\n",
|
||
"**NOTE:** In performance critical cases, explicit cycles are better, but mutable state should be encapsulated."
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "mz5BUTYWXHfIAjGOyinhqi",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "MpSiMp90k75zOtoELK5XSp",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/* Not recommended */\n",
|
||
"var counter = 0\n",
|
||
"for(i in 0..20){\n",
|
||
" counter += i\n",
|
||
"}\n",
|
||
"counter"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "KyyAj8GiWSE3ZOFi2Ct8pD",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 0
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/* recommended */\n",
|
||
"val sum = (0..20).sum()\n",
|
||
"sum"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "NKkj9bAwRFxueaMe7iiov6",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 6
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val intArray: IntArray = IntArray(21){ it -> it + 1 }\n",
|
||
"intArray.sum()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "icUKtPZGuhHjb95pFh77cl",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 12
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Top level functions\n",
|
||
"\n",
|
||
"Don't create a class when a function is enough.\n",
|
||
"\n",
|
||
"Use access modifiers for incapsulation."
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "PSmFAqLCw6ko0q3IWbHk4x",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 18
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * Functions could be defined everywhere in kotlin code. This is a so-called top-level function.\n",
|
||
" */\n",
|
||
"fun doSomething(){\n",
|
||
" println(\"I did it\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"doSomething()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "pKnOC6YRLvZ7Xj6SWth2bP",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 24
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"interface AnInterface{\n",
|
||
" fun doSomethingInAnObject()\n",
|
||
"}\n",
|
||
"\n",
|
||
"object AnObject : AnInterface{\n",
|
||
" /**\n",
|
||
" * This is a member-function\n",
|
||
" */\n",
|
||
" override fun doSomethingInAnObject(){\n",
|
||
" println(\"I did it in an object\")\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"AnObject.doSomethingInAnObject()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "z1PRFmypCJbpbsxEaiVol5",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 30
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun doSomethingSpecial(){\n",
|
||
" val base = \"base\"\n",
|
||
" val special = \"special\"\n",
|
||
" /**\n",
|
||
" * This one is inside another function\n",
|
||
" */\n",
|
||
" fun String.doSomethingInside(){\n",
|
||
" println(\"I did $special inside another function on $this\")\n",
|
||
" }\n",
|
||
" base.doSomethingInside()\n",
|
||
"}\n",
|
||
"//\"ddd\".doSomethingInside()\n",
|
||
"\n",
|
||
"doSomethingSpecial()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "w8hub7Az3lxh78KXeq7Cpv",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 36
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun returnFunction(): (String) -> Unit{\n",
|
||
" fun printStringWithPrefix(str: String){\n",
|
||
" println(\"Prefixed: $str\")\n",
|
||
" }\n",
|
||
" return ::printStringWithPrefix\n",
|
||
" // return { printStringWithPrefix(it) }\n",
|
||
" // return { println(\"Prefixed: $it\") }\n",
|
||
"}\n",
|
||
"\n",
|
||
"returnFunction()(\"Haskel, Boo!\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "QxeCTOYkFSZi5tvWoUvRwU",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 42
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Unit"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "0zwWQ2uPSUrlAoyy1k0GlZ",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 48
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"fun returnUnit(): Unit{\n",
|
||
" // no return statement `Unit` is returned implicitly\n",
|
||
" val b = Unit\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "UxEwPmJN8zFnMxBiL1Kd2W",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 54
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Default parameters"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "2ZAyWaX4qnYZefjc4US2Yj",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun doSomethingWithDefault(a: Int = 0, b: String = \"\") {\n",
|
||
" println(\"A string with a == $a and b == \\\"$b\\\"\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"doSomethingWithDefault()\n",
|
||
"doSomethingWithDefault(2, \"aaa\")\n",
|
||
"doSomethingWithDefault(b = \"fff\", a = 8)\n",
|
||
"doSomethingWithDefault(4, b = \"fff\")\n",
|
||
"doSomethingWithDefault(a = 2, \"fff\")// don't do that"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "Pds7b8enkYPmA9KAaO20zI",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 60
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun integrate(\n",
|
||
" from: Double = 0.0,\n",
|
||
" to: Double = 1.0,\n",
|
||
" step: Double = 0.01,\n",
|
||
" function: (Double) -> Double,\n",
|
||
"): Double {\n",
|
||
" require(to > from)\n",
|
||
" require(step > 0)\n",
|
||
" var sum = 0.0\n",
|
||
" var pos = from\n",
|
||
" while (pos < to) {\n",
|
||
" sum += function(pos)\n",
|
||
" pos += step\n",
|
||
" }\n",
|
||
" return sum*step\n",
|
||
"}\n",
|
||
"\n",
|
||
"integrate { x ->\n",
|
||
" x * x + 2 * x + 1\n",
|
||
"}\n",
|
||
"integrate(0.0, PI) { sin(it) }\n",
|
||
"integrate(0.0, step = 0.02, to = PI) { sin(it) }\n",
|
||
"//integrate(0.0, step = 0.02, PI) { sin(it) }"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "LT2YprLmzrgVcyBo3GKilz",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Function body shortcut"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "lAXRHN4vpo98h93qMABm3D",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun theSameAsBefore(a: Int = 0, b: String = \"\"): String = \"A string with a == $a and b == $b\"\n",
|
||
"\n",
|
||
"class Context(val a: String, val b: String)\n",
|
||
"\n",
|
||
"fun somethingWith(context: Context) = with(context){\n",
|
||
" println(a + b)\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "wEpzn9oKJBKKsBDGytj92U",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": false,
|
||
"hide_output_from_viewers": false,
|
||
"report_properties": {
|
||
"rowId": "vqa5BMfmP7oZwt8sdVLKi8",
|
||
"relativeY": 66
|
||
}
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Trailing lambda\n",
|
||
"\n",
|
||
"Scope is a separate important concept in Kotlin"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "YWQvNkVDKL8m8jqIg1bwLu",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"data class BuildResult internal constructor(val str: String, val int: Int, val optional: Double?){\n",
|
||
" init{\n",
|
||
" require(optional!= null){\"null!\"}\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"class Builder(\n",
|
||
" var str: String = \"\", \n",
|
||
" var int: Int = 0\n",
|
||
"){\n",
|
||
" var optional: Double? = null\n",
|
||
"\n",
|
||
" fun build() = BuildResult(str, int, optional)\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun doWithBuilder(defaultInt: Int, block: Builder.() -> Unit): BuildResult = \n",
|
||
" Builder(int = defaultInt).apply(block).build()\n",
|
||
"\n",
|
||
"doWithBuilder(2){\n",
|
||
" str = \"ff\"\n",
|
||
" optional = 1.0\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "0KGHAp1kvSWJaLGhdf5xk2",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Inheritance"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "qBWuWasNK9nrp0iqoE1ZPA",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"//Interfaces and objects\n",
|
||
"\n",
|
||
"interface AnInterface {\n",
|
||
" val a: Int\n",
|
||
" get() = 4\n",
|
||
" // set(value){\n",
|
||
" // println(value)\n",
|
||
" // }\n",
|
||
" fun doSomething() //= println(\"From interface\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"abstract class AnAbstractClass(override val a: Int): AnInterface{\n",
|
||
" override final fun doSomething() = println(\"From a class\")\n",
|
||
" abstract fun doSomethingElse()\n",
|
||
"}\n",
|
||
"\n",
|
||
"class AClass(override val a: Int) : AnInterface {\n",
|
||
" override fun doSomething() = println(\"From a class\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"class BClass(a: Int) : AnAbstractClass(a) {\n",
|
||
" override fun doSomethingElse() = println(\"something else\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * A singleton (object) is a type (class) which have only one instance\n",
|
||
" */\n",
|
||
"object AnObject : AnInterface {\n",
|
||
" override fun doSomething(): Unit = TODO(\"Not yet implemented\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"/**\n",
|
||
"* Creating an instance\n",
|
||
"*/\n",
|
||
"val instance = AClass(3)\n",
|
||
"\n",
|
||
"/**\n",
|
||
"* Using singleton reference without constructor invocation\n",
|
||
"*/\n",
|
||
"val obj: AnInterface = AnObject\n",
|
||
"\n",
|
||
"/**\n",
|
||
"* Anonymous object\n",
|
||
"*/\n",
|
||
"val anonymous = object : AnInterface {\n",
|
||
" override fun doSomething(): Unit = TODO(\"Not yet implemented\")\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()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "aW9cBvDwbbUsi2CBRrXDPB",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Declaration site variance\n",
|
||
"\n",
|
||
"In consumes, out produces."
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "IvTjF8aNlaknQt9252Tzwl",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"interface Producer<out T>{\n",
|
||
" fun produce(): T\n",
|
||
"}\n",
|
||
"\n",
|
||
"interface Consumer<in T>{\n",
|
||
" fun consume(value: T)\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "O0HQehHaiD0QUaFi62N6C2",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"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
|
||
},
|
||
{
|
||
"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 = 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": [
|
||
"\n",
|
||
"val res: Result<Int> = runCatching<Int> { \n",
|
||
" //error(\"Error happened\")\n",
|
||
" 4\n",
|
||
"}\n",
|
||
"\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()"
|
||
],
|
||
"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"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "cXeTiH13nXoPhTXZLkRnLj",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * The declaration if valid because [TODO] returns Nothing\n",
|
||
" */\n",
|
||
"fun getSomething(): Int? = TODO()\n",
|
||
"\n",
|
||
"fun findSomething(): Int {\n",
|
||
" // early return is valid because `return` operator result is Nothing\n",
|
||
" val found: Int = getSomething() ?: return 2\n",
|
||
" return found + 2\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun checkCondition(): Int {\n",
|
||
" fun conditionSatisfied() = false\n",
|
||
"\n",
|
||
" return if (conditionSatisfied()) {\n",
|
||
" 1\n",
|
||
" } else {\n",
|
||
" //error is Nothing\n",
|
||
" error(\"Condition is not satisfied\")\n",
|
||
" }\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "h11q8FWGKYIcuFOnFOLmBl",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Data class"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "vOQiEaU7CW3kIB3K4W2hEK",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"class SimpleClass(val a: Int, val b: Double, c: Double){\n",
|
||
" override fun toString() = \"SimpleClass(a=$a, b=$b)\"\n",
|
||
"}\n",
|
||
"\n",
|
||
"\n",
|
||
"data class DataClass(val a: Int, val b: Double) {\n",
|
||
" val c get() = b + 1\n",
|
||
"}\n",
|
||
"\n",
|
||
"val simple = SimpleClass(1, 2.0, 3.0)\n",
|
||
"\n",
|
||
"println(simple)\n",
|
||
"\n",
|
||
"val data = DataClass(2, 2.0)\n",
|
||
"val copy = data.copy(b = 22.2)\n",
|
||
"println(copy)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "B7unRz7w7U8OhXejJeFspj",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Nullable truth"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "clBRddjfvKnMe2EMSmDhLd",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Nullable truth.\n",
|
||
" */\n",
|
||
"fun nullableTruth() {\n",
|
||
" class A(val b: Boolean?)\n",
|
||
"\n",
|
||
" val a: A? = A(null) // Compilator warning here\n",
|
||
" //use\n",
|
||
" a?.b == true\n",
|
||
" //instead of\n",
|
||
" a?.b ?: false\n",
|
||
"\n",
|
||
" // The old way\n",
|
||
" val res = if (a == null) {\n",
|
||
" false\n",
|
||
" } else {\n",
|
||
" if (a.b == null) {\n",
|
||
" false\n",
|
||
" } else {\n",
|
||
" a.b\n",
|
||
" }\n",
|
||
" }\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "5BN3u1gHkSamtLIJiQicsV",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Safe call"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "5wCQZq5qasoVCldxVSxxBK",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Safe call and elvis operator\n",
|
||
" */\n",
|
||
"fun idiom12() {\n",
|
||
" val files = File(\"Test\").listFiles()\n",
|
||
" println(files?.size ?: \"empty\")\n",
|
||
"}\n",
|
||
"idiom12()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "v4cP31zyrmBkHP7lnYZWN0",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun printNotNull(any: Any) = println(any)\n",
|
||
"\n",
|
||
"// printNotNull(null) does not work\n",
|
||
"\n",
|
||
"val value: Int? = 2\n",
|
||
"//val value: Int? by lazy{ 2 }\n",
|
||
"\n",
|
||
"//printNotNull(value) // Error\n",
|
||
"if (value != null) {\n",
|
||
" //not guaranteed to work with mutable variable\n",
|
||
" printNotNull(value)\n",
|
||
"}\n",
|
||
"\n",
|
||
"var value1: Int? = 2\n",
|
||
"\n",
|
||
"// Safe call here\n",
|
||
"value1?.let {\n",
|
||
" printNotNull(it) // execute this block if not null\n",
|
||
" //printNotNull(value1) // value is not null here\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "hGZ9h4H8TaYZefCkAmP3Gd",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Nullable assignment"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "hzXkbfAThQ4cKtdGYuLejZ",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Dart-like (?=) nullable assignment\n",
|
||
" */\n",
|
||
"fun idiom11() {\n",
|
||
" var x: String? = null\n",
|
||
" x = x ?: \"Hello\"\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "di2EXkn35CFEja9KMK1Ur5",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Extension functions"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "aC24azwiFpZfA2v3umRb7p",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * Extension function on a String. It is not monkey-patching.\n",
|
||
" */\n",
|
||
"fun String.countOs(): Int = count { it == 'ы' } // implicit this points to String\n",
|
||
"\n",
|
||
"fun Int.printMe() = println(this) // explicit this\n",
|
||
"\n",
|
||
"fun Any?.doSomething(): Int = TODO(\"Don't do that\")\n",
|
||
"\n",
|
||
"fun ((Int) -> Int).evalAndIncrement(): (Int) -> Int = { this.invoke(it) + 1 }\n",
|
||
"\n",
|
||
"// val intFunction: (Int)->Int = {it -1}\n",
|
||
"\n",
|
||
"// val modifiedFunction = intFunction.evalAndIncrement()\n",
|
||
"\n",
|
||
"// println(modifiedFunction(0))\n",
|
||
"\n",
|
||
"\"вылысыпыдыстычка\".countOs().printMe()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "li65OumXRClbEIwURW9DEE",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"infix fun <T: Comparable<T>> ClosedRange<T>.intersect(other: ClosedRange<T>): ClosedRange<T>?{\n",
|
||
" val start = maxOf(this.start, other.start)\n",
|
||
" val end = minOf(this.endInclusive, other.endInclusive)\n",
|
||
" return if(end>=start) start..end else null\n",
|
||
"}\n",
|
||
"\n",
|
||
"(0..8).intersect(6..12)\n",
|
||
"0..8 intersect 6..12"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "cyD7D8tmZJex8pJ3NsufHN",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"fun List<String>.concat() = joinToString(separator = \"\")\n",
|
||
"listOf(\"a\",\"b\",\"c\").concat()\n",
|
||
"listOf(1,2,3).concat()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "tnCskYd7474gKZiYnPHlx4",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Extension properties\n",
|
||
"\n",
|
||
"Remember [property usage guidelines](https://kotlinlang.org/docs/coding-conventions.html#functions-vs-properties)."
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "pJTxzy4MfR710OowVbvf6s",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Extension property (must be virtual)\n",
|
||
" */\n",
|
||
"val List<Number>.odd get() = filter { it.toInt() % 2 == 1 }\n",
|
||
"\n",
|
||
"List(10){it}.odd"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "L7qpVNVtW0Fh6dMX4pR3il",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"var MutableMap<String, String>.a: String?\n",
|
||
" get() = this.get(\"a\")\n",
|
||
" set(value){\n",
|
||
" if(value == null){\n",
|
||
" this.remove(\"a\")\n",
|
||
" } else {\n",
|
||
" this.set(\"a\",value)\n",
|
||
" }\n",
|
||
" }\n",
|
||
"\n",
|
||
"val map = mutableMapOf(\"a\" to \"a\", \"b\" to \"b\")\n",
|
||
"\n",
|
||
"map.a = \"6\"\n",
|
||
"\n",
|
||
"map.a"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "9DG1gyyYvzjbg0EZFfP5Qo",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Extension variable (also must be virtual)\n",
|
||
" */\n",
|
||
"var Array<Int>.second: Int\n",
|
||
" get() = this[1]\n",
|
||
" set(value) {\n",
|
||
" this[1] = value\n",
|
||
" }\n",
|
||
"\n",
|
||
"\n",
|
||
"val array = Array(5){it}\n",
|
||
"array.second = 9\n",
|
||
"array"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "hAjUSxhPqTgmnz9WQYXg3U",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Scope functions (run, with, let)"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "Ziq72FmnnYUYPMy4CamsQ0",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"object AClass{\n",
|
||
" val a = \"a\"\n",
|
||
" val b = \"b\"\n",
|
||
" val c = \"c\"\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun getAClass(): AClass? = null\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * [with]/[run]/[let] are used to create a scope with given argument or receiver\n",
|
||
" */\n",
|
||
"\n",
|
||
"\n",
|
||
"// Simple print of AClass\n",
|
||
"println(\"a = ${AClass.a}, b = ${AClass.b}, c = ${AClass.c}\")\n",
|
||
"\n",
|
||
"// Using `with`\n",
|
||
"val res = with(AClass){\n",
|
||
" // AClass type is the receiver in this scope\n",
|
||
" println(\"a = $a, b = $b, c = $c\")\n",
|
||
" /*return@with*/ \"some value\"\n",
|
||
"}\n",
|
||
"\n",
|
||
"res"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "7wtXhm3FeLejbPp7NEWiz2",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"//using `run`\n",
|
||
"getAClass()?.run {\n",
|
||
" // the same as above\n",
|
||
" println(\"a = $a, b= $b, c = $c\")\n",
|
||
" 2\n",
|
||
"}\n",
|
||
"\n",
|
||
"//Using `let` to compose result. Not recommended using without a need\n",
|
||
"val letResult = getAClass()?.let { arg ->\n",
|
||
" arg.c + arg.a\n",
|
||
"}\n"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "aJGJ3ukmhCchnZwJEzLV3K",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Scope functions (also, apply)"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "r6VfHIkDTBDCIotqNCslOH",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * Using apply/also to add a finalizing action\n",
|
||
" */\n",
|
||
"var i = 2\n",
|
||
"\n",
|
||
"/**\n",
|
||
"* [also] block does not affect the result\n",
|
||
"*/\n",
|
||
"fun getAndIncrement() = i.also { i += 1 } //don't do that\n",
|
||
"\n",
|
||
"println(getAndIncrement())\n",
|
||
"println(i)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "c0kY56DJne2lbwGShOgur6",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"class Rectangle {\n",
|
||
" var length: Number = 0\n",
|
||
" var breadth: Number = 0\n",
|
||
" var color: Int = 0xffffff\n",
|
||
"}\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * Configure properties of an object (apply)\n",
|
||
" * https://kotlinlang.org/docs/idioms.html#configure-properties-of-an-object-apply\n",
|
||
" */\n",
|
||
"val myRectangle = Rectangle().apply {\n",
|
||
" length = 4\n",
|
||
" breadth = 5\n",
|
||
" color = 0xFAFAFA\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun Rectangle(block: Rectangle.() -> Unit): Rectangle = Rectangle().apply(block)\n",
|
||
"\n",
|
||
"val myRectangle2 = Rectangle {\n",
|
||
" length = 4\n",
|
||
" breadth = 5\n",
|
||
" color = 0xFAFAFA\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun Rectangle(length: Number) = Rectangle().apply { this.length = length }\n",
|
||
"\n",
|
||
"Rectangle(8)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "m9HH2IzTy1dbYkBRUeFjh9",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Lists\n",
|
||
"\n",
|
||
"Do not cast List to MutableList!"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "lMgnCCxkRhs62cgTQN5eDK",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * Lists and mutable lists\n",
|
||
" */\n",
|
||
"\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * This method creates a read-only list of strings. One should note that the type of the list is not specified\n",
|
||
" */\n",
|
||
"val list = listOf(\"a\", \"b\", \"c\")\n",
|
||
"\n",
|
||
"println(list[0])\n",
|
||
"println(list.get(1))\n",
|
||
"//println(list.get(4))\n",
|
||
"println(list.getOrNull(4) ?: \"nothing\")"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "pP9PTSy6IXeTC6HITFtBoR",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
"* This one creates a mutable list\n",
|
||
"*/\n",
|
||
"val mutableList: MutableList<String> = mutableListOf(\"a\", \"b\", \"c\")\n",
|
||
"mutableList[2] = \"d\"\n",
|
||
"mutableList.add(\"e\")\n",
|
||
"mutableList += \"f\"\n",
|
||
"mutableList"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "Kx565m7VjuF2RncqW7gw2i",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"listOf(\"a\")::class"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "zKxwfvdRQwsgqRxK5GPTIK",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"var roList = listOf(\"a\", \"b\")\n",
|
||
"roList += setOf(\"c\")\n",
|
||
"roList"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "yK6QD0dvrT98t7dx0pWJ5s",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * This one creates a mutable ArrayList.\n",
|
||
" */\n",
|
||
"val arrayList: ArrayList<String> = arrayListOf(\"a\", \"b\", \"c\")\n",
|
||
"\n",
|
||
"//Danger zone\n",
|
||
"\n",
|
||
"val newList: List<String> = list + \"f\" + mutableList\n",
|
||
"\n",
|
||
"println(newList)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "qSaaZGyHiH9dsL4dtQ8UyE",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"//Bonus\n",
|
||
"\n",
|
||
"val lambdaList = List(3){ it.toString() }\n",
|
||
"println(lambdaList)\n",
|
||
"\n",
|
||
"\n",
|
||
"val builderList: List<Int> = buildList{\n",
|
||
" add(2)\n",
|
||
" add(8)\n",
|
||
" remove(8)\n",
|
||
"}\n",
|
||
"builderList"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "JPSYaCAgOZRveNdFPO15SG",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"// val sequentialList = List(20){it}\n",
|
||
"// sequentialList.zipWithNext{ l, r -> r - l }.forEach{println(it)}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "fQBhhTBHCdc9JkWiMZ6uEh",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Shortcut collection builders"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "rePWgKfjyysV69ubD4fWAR",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * Use shortcut function to provide default values\n",
|
||
" */\n",
|
||
"fun doSomething(additionalArguments: List<String> = emptyList()){\n",
|
||
" TODO()\n",
|
||
" emptyArray<String>()\n",
|
||
" emptySet<String>()\n",
|
||
" emptyMap<String,String>()\n",
|
||
"}\n",
|
||
"emptyList<String>()::class"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "F5RQ5108YJe3pzfN0eAWwm",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Maps"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "TSOQN81tDBKM3Z3oUOHGom",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val map = mutableMapOf(\n",
|
||
" \"key\" to \"a\",\n",
|
||
" \"key2\" to \"b\",\n",
|
||
")\n",
|
||
"\n",
|
||
"//The map could be accessed via indexing operation\n",
|
||
"println(map[\"key\"])\n",
|
||
"map[\"key\"] = \"fff\"\n",
|
||
"println(map[\"key\"])\n",
|
||
"println(map[\"key3\"])"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "cZd2JPB72uAfnx1o8AYjOs",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"//val entry: MutableMap.MutableEntry<String, String> = map.iterator().next()\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * The destructuring declaration for maps and other objects that support `operator fun componentN`\n",
|
||
" */\n",
|
||
"for ((k, v) in map) {\n",
|
||
"//val (k, v) = entry\n",
|
||
"// val k = entry.component1()\n",
|
||
"// val v = entry.component2()\n",
|
||
" println(\"$k -> $v\")\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "hRuaLFdpTsdnt7lYKL2nbN",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"map.forEach { (k, v) -> println(\"$k -> $v\")}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "s1Q65aNWb9YNBZOgxmjotW",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"val (a, b) = Pair(1, 2)\n",
|
||
"\n",
|
||
"val coord = doubleArrayOf(0.0, 1.0, 2.0)\n",
|
||
"\n",
|
||
"val (x,y,z) = coord\n",
|
||
"\n",
|
||
"data class Coordinate(val x: Double, val y: Int)\n",
|
||
"\n",
|
||
"val (x1, y1) = Coordinate(1.0,2)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "t8YITxVsoTt7o9KnnOvO0Z",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Mutable type access decorator\n",
|
||
"\n",
|
||
"To be replaced with qualified getter types soon"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "Ec2mbBaydQnVsjaiThy2rn",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"class AClassWithList{\n",
|
||
" var b: Double = 2.0\n",
|
||
" private set\n",
|
||
"\n",
|
||
" init{\n",
|
||
" b = 5.0\n",
|
||
" }\n",
|
||
"\n",
|
||
" private val _list: MutableList<Int> = ArrayList<Int>()\n",
|
||
" val list: List<Int> get() = _list\n",
|
||
"}\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"val obj = AClassWithList()\n",
|
||
"\n",
|
||
"// obj.b = 10.0 //error\n",
|
||
"obj.list.add(43)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "H8VTPpGlV0VwsHL4Q8lJF9",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Contains operator and ranges"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "GKoCVcgdnSYPjsNCAJIkBB",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"val emailsList = emptyList<String>()\n",
|
||
"\n",
|
||
"// When used directly infix in operator checks if the element is contained in a collection\n",
|
||
"//using `operator fun contains`\n",
|
||
"\n",
|
||
"if (\"john@example.com\" in emailsList) {\n",
|
||
" println(\"is in list\")\n",
|
||
"}\n",
|
||
"\n",
|
||
"if (\"jane@example.com\" !in emailsList) {\n",
|
||
" println(\"not in list\")\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "4mh1Lg6g8OWEIC1Qjgp9tN",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"\n",
|
||
"class DateRange(val start: Instant, val end: Instant)\n",
|
||
"\n",
|
||
"operator fun DateRange.contains(value: Instant): Boolean = value > start && value < end\n",
|
||
"\n",
|
||
"\n",
|
||
"println(Instant.now() in DateRange(Instant.EPOCH, Instant.MAX))"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "1N4A00CAksn2nVg57DRKnp",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"// Another (different) use of `in` is iteration over range or collection using\n",
|
||
"// using `operator fun iterator`\n",
|
||
"\n",
|
||
"for (i in 1..100) {\n",
|
||
" println(i)\n",
|
||
"} // closed range: includes 100\n",
|
||
"\n",
|
||
"(1..100).forEach { i ->\n",
|
||
" println(i)\n",
|
||
"} //the same, but with boxing\n",
|
||
"\n",
|
||
"for (i in 1..<100) {\n",
|
||
" println(i)\n",
|
||
"} // half-open range: does not include 100\n",
|
||
"\n",
|
||
"for (x in 2..10 step 2) {\n",
|
||
" println(x)\n",
|
||
"}\n",
|
||
"for (x in 10 downTo 1) {\n",
|
||
" println(x)\n",
|
||
"}\n",
|
||
"\n",
|
||
"infix fun ClosedRange<Double>.step(step: Double): Sequence<Double> {\n",
|
||
" //TODO check arguments\n",
|
||
" var current = start\n",
|
||
" return sequence {\n",
|
||
" do {\n",
|
||
" yield(current)\n",
|
||
" current += step\n",
|
||
" } while (current <= endInclusive)\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"for (x in 0.0..10.0 step 0.5){\n",
|
||
" println(x)\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "hwJfUD7H5mDtjStAsGppk7",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Map-reduce"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "IsJiqd43JpY7BnZTeHNU4M",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val list: List<Int> = listOf(1, 2, 3, 4, 5, 6)\n",
|
||
"\n",
|
||
"val result = list\n",
|
||
" //.stream().parallel()\n",
|
||
" //.asSequence()\n",
|
||
" .filter { it % 2 == 0 } //select even numbers\n",
|
||
" .map { it * it } // get square of each element\n",
|
||
" //.onEach { println(it) }\n",
|
||
" .sumOf { it } //use one of reduce operations\n",
|
||
" //.reduce { acc: Int, i: Int -> acc + i }\n",
|
||
"\n",
|
||
"result"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "KKT62bidVYF8I147heptAS",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val sequence = sequence {\n",
|
||
" var counter = 1\n",
|
||
" while(true){\n",
|
||
" yield(counter++)\n",
|
||
" yield(counter++)\n",
|
||
" // println(counter)\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"val result = sequence\n",
|
||
" .take(6)\n",
|
||
" .filter { it % 2 == 0 } //select even numbers\n",
|
||
" .map { it * it } // get square of each element\n",
|
||
" //.onEach { println(it) }\n",
|
||
" //.sumOf { it } //use one of reduce operations\n",
|
||
" .reduce { acc: Int, i: Int -> acc + i }\n",
|
||
"\n",
|
||
"result"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "9qcw7ejFSF8QnAGdf1bAI0",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Wrap mutable logic"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "k1eHOcIZbnHDJ8g7ZusArx",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val list = buildList {\n",
|
||
" repeat(10){\n",
|
||
" add(it)\n",
|
||
" }\n",
|
||
"}\n",
|
||
"println(list)\n"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "pJfVynao7enb7Q07lJRGRl",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Scoped resource usage"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "ovz77VglMntuRrJ1uMtSEG",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"val stream = Files.newInputStream(Paths.get(\"file.txt\"))\n",
|
||
"// The resource is automatically closed when leaving the scope\n",
|
||
"stream.bufferedReader().use { reader ->\n",
|
||
" println(reader.readText())\n",
|
||
"}"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "XIX7lDFJ0UiyiJAY4c3Oby",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Factory as parameter and companion factories"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "MizpHzkgkV5TzoM9HFS2zM",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"interface Factory<T : Any> {\n",
|
||
" fun build(str: String): T\n",
|
||
"}\n",
|
||
"\n",
|
||
"data class IntContainer(val arg: Int) {\n",
|
||
" \n",
|
||
" companion object : Factory<IntContainer> {\n",
|
||
" override fun build(str: String) = IntContainer(str.toInt())\n",
|
||
"\n",
|
||
" fun buildSpecial(str: String) = IntContainer(str.toInt())\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"data class DoubleContainer(val arg: Double) {\n",
|
||
" \n",
|
||
" companion object : Factory<DoubleContainer> {\n",
|
||
" override fun build(str: String) = DoubleContainer(str.toDouble())\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun <T : Any> buildContainer(str: String, factory: Factory<T>): T = factory.build(str)\n",
|
||
"\n",
|
||
"\n",
|
||
"buildContainer(\"22\", IntContainer)\n"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "TAnNAjBb2Rc1RRTTICVuZg",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Initialization"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "l8Zp9Da24jvCFJd28sDNFj",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"open class Bad{\n",
|
||
" val value: Int\n",
|
||
"\n",
|
||
" init {\n",
|
||
" value = requestValue()\n",
|
||
" }\n",
|
||
"\n",
|
||
" open fun requestValue(): Int {\n",
|
||
" doSomethingElse()\n",
|
||
" return 2\n",
|
||
" }\n",
|
||
"\n",
|
||
" private fun doSomethingElse(){\n",
|
||
" println(value)\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"Bad()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "xZWJjxthdbhrVOMYfed6UV",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"\n",
|
||
"//Factory functions are preferred to the initialization logic\n",
|
||
"\n",
|
||
"data class Good internal constructor(val value: Int){\n",
|
||
" init {\n",
|
||
" //Initialization block is there to check arguments\n",
|
||
" require(value >= 0)\n",
|
||
" }\n",
|
||
"\n",
|
||
" companion object\n",
|
||
"}\n",
|
||
"\n",
|
||
"fun requestValue(): Int = TODO()\n",
|
||
"\n",
|
||
"// This is the factory-function\n",
|
||
"fun Good() = Good(requestValue())\n",
|
||
"\n",
|
||
"\n",
|
||
"// additional constructor-like builders could be added to the companion\n",
|
||
"\n",
|
||
"@OptIn(ExperimentalUnsignedTypes::class)\n",
|
||
"fun Good.Companion.build(value: UInt) = Good(value.toInt())\n",
|
||
"\n",
|
||
"Good.build(32U)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "2oRxs51NNlsoJD7UIx3exC",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Delegates"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "jvl9An4EkBkWd9B1JX4ju9",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"class ClassWithALazyProperty{\n",
|
||
" //Use lazy delegate for something that should be calculated ones on first call\n",
|
||
" val lazyValue by lazy {\n",
|
||
" //Do dome heavy logic here\n",
|
||
" println(\"Initialized\")\n",
|
||
" 22\n",
|
||
" }\n",
|
||
"\n",
|
||
" val getterValue: Int get(){\n",
|
||
" println(\"got\")\n",
|
||
" return 33\n",
|
||
" }\n",
|
||
"}\n",
|
||
"val lazyClass = ClassWithALazyProperty()\n",
|
||
"lazyClass.lazyValue\n",
|
||
"lazyClass.lazyValue\n",
|
||
"lazyClass.getterValue\n",
|
||
"lazyClass.getterValue"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "CqN0VKctxRWd4N4RrKC90M",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"//Using other delegates\n",
|
||
"val map = mutableMapOf(\"a\" to 1, \"b\" to 2)\n",
|
||
"\n",
|
||
"var a: Int by map\n",
|
||
"\n",
|
||
"println(a)\n",
|
||
"a = 3\n",
|
||
"println(map)"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "TYw8wCso8aGvqvd2XviRcH",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Inline functions"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "OkBtMlEkvfaglVXzlzq5dU",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Definition of inline function\n",
|
||
" */\n",
|
||
"inline fun List<Int>.forEachOdd(block: (Int) -> Unit) = forEach {\n",
|
||
" if (it % 2 == 1) block(it)\n",
|
||
"}\n",
|
||
"\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * The demonstration of use of inline [forEach] function with non-local return\n",
|
||
" */\n",
|
||
"fun foo(): Int {\n",
|
||
" listOf(1, 2, 3, 4, 5).forEach {\n",
|
||
" if (it == 3) return it // non-local return directly to the caller of foo()\n",
|
||
" print(\"$it, \")\n",
|
||
" }\n",
|
||
" println(\"this point is unreachable\")\n",
|
||
" return 0\n",
|
||
"}\n",
|
||
"foo()"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "kz2Dq5cDNhfbfgI6mXv5yU",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"\n",
|
||
"/**\n",
|
||
" * Using inline function for type reification during the compile time\n",
|
||
" */\n",
|
||
"inline fun <reified T> List<T>.prettyPrint() = forEach {\n",
|
||
" when (T::class) {\n",
|
||
" Double::class -> println(\"Double: ${it as Double}\")\n",
|
||
" Int::class -> println(\"Int: ${it as Int}\")\n",
|
||
" else -> it.toString()\n",
|
||
" }\n",
|
||
"}\n",
|
||
"\n",
|
||
"inline fun <reified T> prettyPrintOne(arg: T) = listOf(arg).prettyPrint()\n",
|
||
"\n",
|
||
"listOf(1, 2, 3).prettyPrint()\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * **WARNING** inline functions are an advanced feature and should be used only for\n",
|
||
" * reification or non-local return\n",
|
||
" * NOT for optimization.\n",
|
||
" */"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "drMX3vZ5PBfpBXhCZM1zc5",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"## Collections and boxing"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "6I3SqcgBGWPqpKZRhNDfAM",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"source": [
|
||
"/**\n",
|
||
" * Values are boxed. Each call is indirect\n",
|
||
" */\n",
|
||
"val list: List<Double> = List(20) { it.toDouble() }\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * Still boxed\n",
|
||
" */\n",
|
||
"val genericArray: Array<Double> = Array(20) { it.toDouble() }\n",
|
||
"\n",
|
||
"/**\n",
|
||
" * Non-boxed\n",
|
||
" */\n",
|
||
"val specializedArray: DoubleArray = DoubleArray(20) { it.toDouble() }"
|
||
],
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "ieHZ3zzSufTtNWM11pIuh1",
|
||
"type": "CODE",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"execution_count": null
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"Вопросы для самоконтроля:\n",
|
||
"\n",
|
||
"1.\tВ какой момент происходит интерполяция строк? Во время компиляции или во время выполнения?\n",
|
||
"2.\tВо что компилируются функции верхнего уровня?\n",
|
||
"3.\tЧем отличается Unit от других объектов.\n",
|
||
"4.\tКакой порядок разрешения функций со значениями по умолчанию.\n",
|
||
"5.\tЧто не является выражением в Котлин?\n",
|
||
"6.\tКто такой Волдеморт?\n",
|
||
"7.\tВ чем отличие declaration site variance от use site variance. Какой из вариантов поддерживается в Котлин?\n",
|
||
"8.\tКак выводится тип выражения try?\n",
|
||
"9.\tЕсть ли разница между `Nothing` и `Nothing?` ?\n",
|
||
"10.\tКакие ограничения наложены на конструктор data class.\n",
|
||
"11.\tВ каком случае вычисляется правая часть выражения безопасного вызова?\n",
|
||
"12.\tЧто такое Элвис оператор?\n",
|
||
"13.\tКак работает стирание дженериков при разрешении расширений?\n",
|
||
"14.\tМожет ли у свойства-расширения быть собственное значение?\n",
|
||
"15.\tЧем отличается run от with?\n",
|
||
"16.\tСтоит ли использовать scope функции везде, где это возможно.\n",
|
||
"17.\tЧем отличается arrayListOf()` от `mutableListOf()`?\n",
|
||
"18.\tList в Kotlin всегда реализует List в Java при интеропе?\n",
|
||
"19.\tМожно ли сделать собствен карту get и set при помощи квадратных скобок?\n",
|
||
"20.\tВ чем отличие forEach в стандартной библиотеке Котлин и Java?\n",
|
||
"21.\tКак работают функции componentN?\n",
|
||
"22.\tПочему в Котлин нет диапазонов для чисел с плавающей точкой?\n",
|
||
"23.\tКакой оператор должен быть реализован типе для того, чтобы он стал делегатом?\n",
|
||
"24.\tМожно ли делегировать при помощи расширения?\n",
|
||
"25.\tВ какой момент происходит инлайнинг инлайн функции?\n",
|
||
"26.\tМожет ли быть сделана реификация типа без инлайна?\n",
|
||
"27.\tВ каких случаях следует использовать тип Array?"
|
||
],
|
||
"attachments": {},
|
||
"metadata": {
|
||
"datalore": {
|
||
"node_id": "v6c4s0X9jSpc2ZDPAuXAz7",
|
||
"type": "MD",
|
||
"hide_input_from_viewers": true,
|
||
"hide_output_from_viewers": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"metadata": {},
|
||
"cell_type": "code",
|
||
"source": "",
|
||
"outputs": [],
|
||
"execution_count": null
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Kotlin",
|
||
"language": "kotlin",
|
||
"name": "kotlin"
|
||
},
|
||
"datalore": {
|
||
"computation_mode": "JUPYTER",
|
||
"package_manager": "pip",
|
||
"base_environment": "default",
|
||
"packages": [],
|
||
"report_row_ids": [
|
||
"xIF3Up82GVsiV1Ceze6Si3",
|
||
"ypTKLK2KvAZfnMbTgaVqNK",
|
||
"qyGLHGsLl6mRCaOjpZBTD3",
|
||
"7tql3kbsQ9JIbbEfghi48B",
|
||
"BQz86nEWOj77fxXQ8iS47U",
|
||
"RTl3zV3tStzlLoIHSvEZiV",
|
||
"xmBQdVRhRGLsw0t87vxQW7",
|
||
"MpSiMp90k75zOtoELK5XSp",
|
||
"vqa5BMfmP7oZwt8sdVLKi8"
|
||
],
|
||
"report_link": "https://datalore.jetbrains.com/report/ptQDfQAcrjNxzIO0AEqovZ/VXj2xqMTETu24Qra9ydiLo",
|
||
"version": 3
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
}
|