diff --git a/.github/workflows/verify-samples.yml b/.github/workflows/verify-samples.yml new file mode 100644 index 00000000..ffb2903e --- /dev/null +++ b/.github/workflows/verify-samples.yml @@ -0,0 +1,24 @@ +name: Verify samples + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + - name: Run a verifier + uses: AlexanderPrendota/kotlin-samples-verifier@master + with: + push-repository: 'https://github.com/AlexanderPrendota/kotlin-compiler-server' + tag-filter: '#tag="code" & class="language-run-kotlin" & !validate="false"' + push-path: 'src/test/resources/test-compile-data/jvm/kotlin-by-example' + username: '${{ secrets.KOTLIN_BY_EXAMPLE_TOKEN }}' #token with an access to create PR in push-repository and issue in this repository + diff --git a/README.md b/README.md index 5131e76a..6303c490 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Kotlin by Example +[![Obsolete JetBrains project](http://jb.gg/badges/obsolete.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) -This is sources of [Kotlin Examples](https://play.kotlinlang.org/byExample/overview). +The repository is archived, please refer to [Kotlin Tour](https://kotlinlang.org/docs/kotlin-tour-welcome.html) for up-to-date Kotlin learning materials. + +------------ ### How to make example @@ -11,13 +14,11 @@ Create markdown file in `examples` folder. Lorem ipsum dolor sit `amet`, consectetur adipisicing elit. Aspernatur, molestias, velit? -
-`​`​`kotlin +`​`​`run-kotlin fun main(args: Array) { println("Hello from template") } `​`​` -
1. Epsum `factorial` non deposit quid pro quo hic escorol. 2. Souvlaki ignitus carborundum e pluribus unum. diff --git a/examples/01_introduction/01_Hello world.md b/examples/01_introduction/01_Hello world.md index 63989721..fed021f2 100755 --- a/examples/01_introduction/01_Hello world.md +++ b/examples/01_introduction/01_Hello world.md @@ -1,8 +1,6 @@ # Hello World -
- -```kotlin +```run-kotlin package org.kotlinlang.play // 1 fun main() { // 2 @@ -10,20 +8,7 @@ fun main() { // 2 } ``` -
- 1. Kotlin code is usually defined in packages. Package specification is optional: If you don't specify a package in a source file, its content goes to the default package. -2. An entry point to a Kotlin application is the `main` function. In Kotlin 1.3, you can declare `main` without any parameters. The return type is not specified, which means that the function returns nothing. -3. `println` writes a line to the standard output. It is imported implicitly. Also note that semicolons are optional. - -In Kotlin versions earlier than 1.3, the `main` function must have a parameter of type `Array`. - -
- -```kotlin -fun main(args: Array) { - println("Hello, World!") -} -``` +2. An entry point to a Kotlin application is the `main` function. You can declare it without any parameters. The return type is not specified, which means that the function returns nothing. +3. `println` writes a line to the standard output. It is imported implicitly. Also, note that semicolons at the end of code lines are optional. -
diff --git a/examples/01_introduction/02_Functions.md b/examples/01_introduction/02_Functions.md index 59858ac1..216941db 100755 --- a/examples/01_introduction/02_Functions.md +++ b/examples/01_introduction/02_Functions.md @@ -2,9 +2,7 @@ ### Default Parameter Values and Named Arguments -
- -```kotlin +```run-kotlin fun printMessage(message: String): Unit { // 1 println(message) } @@ -25,11 +23,10 @@ fun main() { printMessageWithPrefix("Hello") // 7 printMessageWithPrefix(prefix = "Log", message = "Hello") // 8 println(sum(1, 2)) // 9 + println(multiply(2, 4)) // 10 } ``` -
- 1. A simple function that takes a parameter of type `String` and returns `Unit` (i.e., no return value). 2. A function that takes a second [optional parameter with default value](https://kotlinlang.org/docs/reference/functions.html#default-arguments) `Info`. The return type is omitted, meaning that it's actually `Unit`. 3. A function that returns an integer. @@ -38,15 +35,14 @@ fun main() { 6. Calls the function with two parameters, passing values for both of them. 7. Calls the same function omitting the second one. The default value `Info` is used. 8. Calls the same function using [named arguments](https://kotlinlang.org/docs/reference/functions.html#named-arguments) and changing the order of the arguments. -9. Prints the result of a function call. +9. Prints the result of the `sum` function call. +10. Prints the result of the `multiply` function call. ### Infix Functions Member functions and extensions with a single parameter can be turned into [infix functions](https://kotlinlang.org/docs/reference/functions.html#infix-notation). -
- -```kotlin +```run-kotlin fun main() { infix fun Int.times(str: String) = str.repeat(this) // 1 @@ -70,8 +66,6 @@ class Person(val name: String) { } ``` -
- 1. Defines an infix extension function on `Int`. 2. Calls the infix function. 3. Creates a `Pair` by calling the infix function `to` from the standard library. @@ -85,9 +79,7 @@ Note that the example uses [local functions](https://kotlinlang.org/docs/referen Certain functions can be "upgraded" to [operators](https://kotlinlang.org/docs/reference/operator-overloading.html), allowing their calls with the corresponding operator symbol. -
- -```kotlin +```run-kotlin fun main() { //sampleStart operator fun Int.times(str: String) = str.repeat(this) // 1 @@ -100,8 +92,6 @@ fun main() { } ``` -
- 1. This takes the infix function from above one step further using the `operator` modifier. 2. The operator symbol for `times()` is `*` so that you can call the function using `2 * "Bye"`. 3. An operator function allows easy range access on strings. @@ -111,9 +101,7 @@ fun main() { [Varargs](https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs) allow you to pass any number of arguments by separating them with commas. -
- -```kotlin +```run-kotlin fun main() { //sampleStart fun printAll(vararg messages: String) { // 1 @@ -132,12 +120,11 @@ fun main() { fun log(vararg entries: String) { printAll(*entries) // 5 } + log("Hello", "Hallo", "Salut", "Hola", "你好") //sampleEnd } ``` -
- 1. The `vararg` modifier turns a parameter into a vararg. 2. This allows calling `printAll` with any number of string arguments. 3. Thanks to named parameters, you can even add another parameter of the same type after the vararg. This wouldn't be allowed in Java because there's no way to pass a value. diff --git a/examples/01_introduction/03_Variables.md b/examples/01_introduction/03_Variables.md index 8c940615..a983dcd2 100755 --- a/examples/01_introduction/03_Variables.md +++ b/examples/01_introduction/03_Variables.md @@ -4,9 +4,7 @@ Kotlin has powerful type inference. While you can explicitly declare the type of compiler do the work by inferring it. Kotlin does not enforce immutability, though it is recommended. In essence use *val* over *var*. -
- -```kotlin +```run-kotlin fun main() { //sampleStart var a: String = "initial" // 1 @@ -17,15 +15,11 @@ fun main() { } ``` -
- -1. Declares a mutable variable and initializing it. -2. Declares an immutable variable and initializing it. -3. Declares an immutable variable and initializing it without specifying the type. The compiler infers the type `Int`. - -
+1. Declares a mutable variable and initializes it. +2. Declares an immutable variable and initializes it. +3. Declares an immutable variable and initializes it without specifying the type. The compiler infers the type `Int`. -```kotlin +```run-kotlin fun main() { //sampleStart var e: Int // 1 @@ -33,17 +27,14 @@ fun main() { //sampleEnd } ``` - -
+{validate="false"} 1. Declares a variable without initialization. 2. An attempt to use the variable causes a compiler error: `Variable 'e' must be initialized`. You're free to choose when you initialize a variable, however, it must be initialized before the first read. - -
-```kotlin +```run-kotlin fun someCondition() = true fun main() { @@ -61,8 +52,6 @@ fun main() { } ``` -
- 1. Declares a variable without initialization. 2. Initializes the variable with different values depending on some condition. 3. Reading the variable is possible because it's already been initialized. diff --git a/examples/01_introduction/04_Null Safety.md b/examples/01_introduction/04_Null Safety.md index aaa44da2..5279a9e0 100755 --- a/examples/01_introduction/04_Null Safety.md +++ b/examples/01_introduction/04_Null Safety.md @@ -2,9 +2,7 @@ In an effort to rid the world of `NullPointerException`, variable types in Kotlin don't allow the assignment of `null`. If you need a variable that can be null, declare it nullable by adding `?` at the end of its type. -
- -```kotlin +```run-kotlin fun main() { //sampleStart var neverNull: String = "This can't be null" // 1 @@ -28,8 +26,7 @@ fun main() { //sampleEnd } ``` - -
+{validate="false"} 1. Declares a non-`null` String variable. 2. When trying to assign `null` to non-nullable variable, a compilation error is produced. @@ -46,9 +43,7 @@ fun main() { Sometimes Kotlin programs need to work with null values, such as when interacting with external Java code or representing a truly absent state. Kotlin provides null tracking to elegantly deal with such situations. -
- -```kotlin +```run-kotlin //sampleStart fun describeString(maybeString: String?): String { // 1 if (maybeString != null && maybeString.length > 0) { // 2 @@ -64,8 +59,6 @@ fun main() { } ``` -
- 1. A function that takes in a nullable string and returns its description. 2. If the given string is not `null` and not empty, return information about its length. 3. Otherwise, tell the caller that the string is empty or null. diff --git a/examples/01_introduction/05_Classes.md b/examples/01_introduction/05_Classes.md index 2b17c045..b206ed66 100755 --- a/examples/01_introduction/05_Classes.md +++ b/examples/01_introduction/05_Classes.md @@ -3,10 +3,8 @@ The [class declaration](https://kotlinlang.org/docs/reference/classes.html#classes) consists of the class name, the class header (specifying its type parameters, the primary constructor etc.) and the class body, surrounded by curly braces. Both the header and the body are optional; if the class has no body, curly braces can be omitted. - -
-```kotlin +```run-kotlin class Customer // 1 class Contact(val id: Int, var email: String) // 2 @@ -22,8 +20,6 @@ fun main() { } ``` -
- 1. Declares a class named `Customer` without any properties or user-defined constructors. A non-parameterized default constructor is created by Kotlin automatically. 2. Declares a class with two properties: immutable `id` and mutable `email`, and a constructor with two parameters `id` and `email`. 3. Creates an instance of the class `Customer` via the default constructor. Note that there is no `new` keyword in Kotlin. diff --git a/examples/01_introduction/06_Generics.md b/examples/01_introduction/06_Generics.md index ef5290d1..ec9a83c3 100755 --- a/examples/01_introduction/06_Generics.md +++ b/examples/01_introduction/06_Generics.md @@ -6,9 +6,7 @@ The first way to use generics in Kotlin is creating generic classes. -
- -```kotlin +```run-kotlin //sampleStart class MutableStack(vararg items: E) { // 1 @@ -44,7 +42,6 @@ fun main() { ``` -
1. Defines a generic class `MutableStack` where `E` is called the _generic type parameter_. At use-site, it is assigned to a specific type such as `Int` by declaring a `MutableStack`. 2. Inside the generic class, `E` can be used as a parameter like any other type. @@ -57,9 +54,8 @@ Note that the implementation makes heavy use of Kotlin's shorthand syntax for fu You can also [generify functions](https://kotlinlang.org/docs/reference/generics.html#generic-functions) if their logic is independent of a specific type. For instance, you can write a utility function to create mutable stacks: -
-```kotlin +```run-kotlin class MutableStack(vararg items: E) { // 1 private val elements = items.toMutableList() @@ -87,6 +83,4 @@ fun main() { //sampleEnd ``` -
- -Note that the compiler can infer the generic type from the parameters of `mutableStackOf` so that you don't have to write `mutableStackOf(...)`. +Note that the compiler can infer the generic type from the parameters of `mutableStackOf` so that you don't have to write `mutableStackOf(...)`. diff --git a/examples/01_introduction/07_Inheritance.md b/examples/01_introduction/07_Inheritance.md index 50805c53..a7c41e23 100755 --- a/examples/01_introduction/07_Inheritance.md +++ b/examples/01_introduction/07_Inheritance.md @@ -2,9 +2,7 @@ Kotlin fully supports the traditional object-oriented inheritance mechanism. -
- -```kotlin +```run-kotlin open class Dog { // 1 open fun sayHello() { // 2 println("wow wow!") @@ -23,8 +21,6 @@ fun main() { } ``` -
- 1. Kotlin classes are _final_ by default. If you want to allow the class inheritance, mark the class with the `open` modifier. 2. Kotlin methods are also _final_ by default. As with the classes, the `open` modifier allows overriding them. 3. A class inherits a superclass when you specify the `: SuperclassName()` after its name. The empty parentheses `()` indicate an invocation of the superclass default constructor. @@ -32,9 +28,7 @@ fun main() { ### Inheritance with Parameterized Constructor -
- -```kotlin +```run-kotlin //sampleStart open class Tiger(val origin: String) { fun sayHello() { @@ -51,16 +45,13 @@ fun main() { //sampleEnd ``` -
1. If you want to use a parameterized constructor of the superclass when creating a subclass, provide the constructor arguments in the subclass declaration. ### Passing Constructor Arguments to Superclass -
- -```kotlin +```run-kotlin //sampleStart open class Lion(val name: String, val origin: String) { fun sayHello() { @@ -77,9 +68,6 @@ fun main() { //sampleEnd ``` -
- - 1. `name` in the `Asiatic` declaration is neither a `var` nor `val`: it's a constructor argument, whose value is passed to the `name` property of the superclass `Lion`. 2. Creates an `Asiatic` instance with the name `Rufo`. The call invokes the `Lion` constructor with arguments `Rufo` and `India`. diff --git a/examples/02_control_flow/01_When.md b/examples/02_control_flow/01_When.md index 627faf14..558890b3 100755 --- a/examples/02_control_flow/01_When.md +++ b/examples/02_control_flow/01_When.md @@ -4,9 +4,7 @@ Instead of the widely used `switch` statement, Kotlin provides the more flexible ## When Statement -
- -```kotlin +```run-kotlin fun main() { cases("Hello") cases(1) @@ -15,8 +13,8 @@ fun main() { cases("hello") } -fun cases(obj: Any) { // 1 - when (obj) { +fun cases(obj: Any) { + when (obj) { // 1 1 -> println("One") // 2 "Hello" -> println("Greeting") // 3 is Long -> println("Long") // 4 @@ -28,22 +26,18 @@ fun cases(obj: Any) { // 1 class MyClass ``` -
- 1. This is a `when` statement. -2. Checks whether `obj` equals to one. -3. Checks whether `obj` equals to `Hello`. +2. Checks whether `obj` equals to `1`. +3. Checks whether `obj` equals to `"Hello"`. 4. Performs type checking. 5. Performs inverse type checking. 6. Default statement (might be omitted). Note that all branch conditions are checked sequentially until one of them is satisfied. So, only the first suitable branch will be executed. -## When Expresion - -
+## When Expression -```kotlin +```run-kotlin fun main() { println(whenAssign("Hello")) println(whenAssign(3.4)) @@ -64,10 +58,9 @@ fun whenAssign(obj: Any): Any { class MyClass ``` -
1. This is a `when` expression. -2. Sets the value to `"one"` if `obj` equals to one. -3. Sets the value to one if `obj` equals to `Hello`. +2. Sets the value to `"one"` if `obj` equals to `1`. +3. Sets the value to one if `obj` equals to `"Hello"`. 4. Sets the value to `false` if `obj` is an instance of `Long`. -5. Sets the value "42" if none of the previous conditions are satisfied. Unlike in `when` _statement_, the default branch is usually required in `when` _expression_, except the case when the compiler can check that other branches cover all possible cases. +5. Sets the value `42` if none of the previous conditions are satisfied. Unlike in `when` _statement_, the default branch is usually required in `when` _expression_, except the case when the compiler can check that other branches cover all possible cases. diff --git a/examples/02_control_flow/02_Loops.md b/examples/02_control_flow/02_Loops.md index cc57c068..6194f1c1 100755 --- a/examples/02_control_flow/02_Loops.md +++ b/examples/02_control_flow/02_Loops.md @@ -1,4 +1,4 @@ -#Loops +# Loops Kotlin supports all the commonly used loops: `for`, `while`, `do-while` @@ -6,9 +6,7 @@ Kotlin supports all the commonly used loops: `for`, `while`, `do-while` `for` in Kotlin works the same way as in most languages. -
- -```kotlin +```run-kotlin fun main(args: Array) { //sampleStart val cakes = listOf("carrot", "cheese", "chocolate") @@ -21,17 +19,13 @@ fun main(args: Array) { } ``` -
- 1. Loops through each cake in the list. ### `while` and `do-while` `while` and `do-while` constructs work similarly to most languages as well. -
- -```kotlin +```run-kotlin fun eatACake() = println("Eat a Cake") fun bakeACake() = println("Bake a Cake") @@ -52,8 +46,6 @@ fun main(args: Array) { } ``` -
- 1. Executes the block while the condition is true. 2. Executes the block first and then checking the condition. @@ -61,9 +53,7 @@ fun main(args: Array) { You can define your own iterators in your classes by implementing the `iterator` operator in them. -
- -```kotlin +```run-kotlin class Animal(val name: String) class Zoo(val animals: List) { @@ -84,8 +74,6 @@ fun main() { } ``` -
- 1. Defines an iterator in a class. It must be named `iterator` and have the `operator` modifier. 2. Returns the iterator that meets the following method requirements: * `next()`: `Animal` diff --git a/examples/02_control_flow/03_Ranges.md b/examples/02_control_flow/03_Ranges.md index 36df5d70..2246e834 100755 --- a/examples/02_control_flow/03_Ranges.md +++ b/examples/02_control_flow/03_Ranges.md @@ -2,9 +2,7 @@ There is a set of tools for defining ranges in Kotlin. Let's have a brief look at them. -
- -```kotlin +```run-kotlin fun main() { //sampleStart for(i in 0..3) { // 1 @@ -12,12 +10,17 @@ fun main() { } print(" ") - for(i in 2..8 step 2) { // 2 + for(i in 0 until 3) { // 2 + print(i) + } + print(" ") + + for(i in 2..8 step 2) { // 3 print(i) } print(" ") - for (i in 3 downTo 0) { // 3 + for (i in 3 downTo 0) { // 4 print(i) } print(" ") @@ -26,17 +29,14 @@ fun main() { } ``` -
- -1. Iterates over a range starting from 0 up to 3 (inclusive). -2. Iterates over a range with a custom increment step for consecutive elements. -5. Iterates over a range in _reverse_ order. +1. Iterates over a range starting from 0 up to 3 (inclusive). Like 'for(i=0; i<=3; ++i)' in other programming languages (C/C++/Java). +2. Iterates over a range starting from 0 up to 3 (exclusive). Like for loop in Python or like 'for(i=0; i<3; ++i)' in other programming languages (C/C++/Java). +3. Iterates over a range with a custom increment step for consecutive elements. +4. Iterates over a range in _reverse_ order. Char ranges are also supported: -
- -```kotlin +```run-kotlin fun main() { //sampleStart for (c in 'a'..'d') { // 1 @@ -53,32 +53,26 @@ fun main() { } ``` -
- 1. Iterates over a char range in alphabetical order. 2. Char ranges support `step` and `downTo` as well. Ranges are also useful in `if` statements: -
- -```kotlin +```run-kotlin fun main() { //sampleStart val x = 2 - if (x in 1..10) { // 1 - print(x) + if (x in 1..5) { // 1 + print("x is in range from 1 to 5") } - print(" ") + println() - if (x !in 1..4) { // 2 - print(x) + if (x !in 6..10) { // 2 + print("x is not in range from 6 to 10") } //sampleEnd } ``` -
- 1. Checks if a value is in the range. 2. `!in` is the opposite of `in`. diff --git a/examples/02_control_flow/04_Equality Checks.md b/examples/02_control_flow/04_Equality Checks.md index 91721530..c5e316fe 100755 --- a/examples/02_control_flow/04_Equality Checks.md +++ b/examples/02_control_flow/04_Equality Checks.md @@ -2,12 +2,10 @@ Kotlin uses `==` for structural comparison and `===` for referential comparison. -More precisely, `a == b` compiles down to `a == null ? b == null : a.equals(b)`. +More precisely, `a == b` compiles down to `if (a == null) b == null else a.equals(b)`. -
- -```kotlin -fun main(args: Array) { +```run-kotlin +fun main() { //sampleStart val authors = setOf("Shakespeare", "Hemingway", "Twain") @@ -19,7 +17,5 @@ fun main(args: Array) { } ``` -
- 1. Returns `true` because it calls `authors.equals(writers)` and sets ignore element order. 2. Returns `false` because `authors` and `writers` are distinct references. diff --git a/examples/02_control_flow/05_Conditional expression.md b/examples/02_control_flow/05_Conditional expression.md index f0d19dcb..51cf44bb 100755 --- a/examples/02_control_flow/05_Conditional expression.md +++ b/examples/02_control_flow/05_Conditional expression.md @@ -2,9 +2,7 @@ There is no ternary operator `condition ? then : else` in Kotlin. Instead, `if` may be used as an expression: -
- -```kotlin +```run-kotlin fun main() { //sampleStart fun max(a: Int, b: Int) = if (a > b) a else b // 1 @@ -14,6 +12,4 @@ fun main() { } ``` -
- 1. `if` is an expression here: it returns a value. diff --git a/examples/03_special_classes/01_Data classes.md b/examples/03_special_classes/01_Data classes.md index fc1afbdf..336488cb 100755 --- a/examples/03_special_classes/01_Data classes.md +++ b/examples/03_special_classes/01_Data classes.md @@ -1,42 +1,45 @@ # Data Classes -[Data classes](https://kotlinlang.org/docs/reference/data-classes.html) make it easy to create classes that are used to store values. Such classes are automatically provided with methods for copying, getting a string representation, and using instances in collections. - -
- -```kotlin -data class User(val name: String, val id: Int) // 1 +[Data classes](https://kotlinlang.org/docs/reference/data-classes.html) make it easy to create classes that are used to store values. Such classes are automatically provided with methods for copying, getting a string representation, and using instances in collections. You can override these methods with your own implementations in the class declaration. +```run-kotlin +data class User(val name: String, val id: Int) { // 1 + override fun equals(other: Any?) = + other is User && other.id == this.id // 2 +} fun main() { val user = User("Alex", 1) - println(user) // 2 + println(user) // 3 val secondUser = User("Alex", 1) val thirdUser = User("Max", 2) - println("user == secondUser: ${user == secondUser}") // 3 + println("user == secondUser: ${user == secondUser}") // 4 println("user == thirdUser: ${user == thirdUser}") - println(user.hashCode()) // 4 + // hashCode() function + println(user.hashCode()) // 5 + println(secondUser.hashCode()) println(thirdUser.hashCode()) // copy() function - println(user.copy()) // 5 - println(user.copy("Max")) // 6 - println(user.copy(id = 2)) // 7 - - println("name = ${user.component1()}") // 8 + println(user.copy()) // 6 + println(user === user.copy()) // 7 + println(user.copy("Max")) // 8 + println(user.copy(id = 3)) // 9 + + println("name = ${user.component1()}") // 10 println("id = ${user.component2()}") } ``` -
- -1. Defines a data class with the `data` modifier. -2. Method `toString` is auto-generated, which makes `println` output look nice. -3. Auto-generated `equals` considers two instances equal if all their properties are equal. -4. Equal data class instances have equal `hashCode()`. -5. Auto-generated `copy` function makes it easy to create a new instance. -6. When copying, you can change values of certain properties. `copy` accepts arguments in the same order as the class constructor. -7. Use `copy` with named arguments to change the value despite of the properties order. -8. Auto-generated `componentN` functions let you get the values of properties in the order of declaration. +1. Defines a data class with the `data` modifier. +2. Override the default `equals` method by declaring users equal if they have the same `id`. +3. Method `toString` is auto-generated, which makes `println` output look nice. +4. Our custom `equals` considers two instances equal if their `id`s are equal. +5. Data class instances with exactly matching attributes have the same `hashCode`. +6. Auto-generated `copy` function makes it easy to create a new instance. +7. `copy` creates a new instance, so the object and its copy have distinct references. +8. When copying, you can change values of certain properties. `copy` accepts arguments in the same order as the class constructor. +9. Use `copy` with named arguments to change the value despite of the properties order. +10. Auto-generated `componentN` functions let you get the values of properties in the order of declaration. diff --git a/examples/03_special_classes/02_Enum.md b/examples/03_special_classes/02_Enum.md index 79cc8cf2..415346bc 100755 --- a/examples/03_special_classes/02_Enum.md +++ b/examples/03_special_classes/02_Enum.md @@ -2,9 +2,7 @@ [Enum classes](https://kotlinlang.org/docs/reference/enum-classes.html) are used to model types that represent a finite set of distinct values, such as directions, states, modes, and so forth. -
- -```kotlin +```run-kotlin enum class State { IDLE, RUNNING, FINISHED // 1 } @@ -21,17 +19,13 @@ fun main() { ``` -
- -1. Defines a simple enum class with three enum instances. The number of instances is always finite and they are all distinct. -2. Accesses an enum instance via the class name. +1. Defines a simple enum class with three enum constants. The number of constants is always finite and they are all distinct. +2. Accesses an enum constant via the class name. 3. With enums, the compiler can infer if a `when`-expression is exhaustive so that you don't need the `else`-case. -Enums may contain properties and methods like other classes, separated from the list of instances by a semicolon. +Enums may contain properties and methods like other classes, separated from the list of enum constants by a semicolon. -
- -```kotlin +```run-kotlin enum class Color(val rgb: Int) { // 1 RED(0xFF0000), // 2 @@ -47,15 +41,15 @@ fun main() { println(red) // 4 println(red.containsRed()) // 5 println(Color.BLUE.containsRed()) // 6 + println(Color.YELLOW.containsRed()) // 7 } ``` -
- 1. Defines an enum class with a property and a method. -2. Each instance must pass an argument for the constructor parameter. -3. Enum class members are separated from the instance definitions by a semicolon. -4. The default `toString` returns the name of the instance, here `"RED"`. -5. Calls a method on a enum instance. +2. Each enum constant must pass an argument for the constructor parameter. +3. Enum class members are separated from the constant definitions by a semicolon. +4. The default `toString` returns the name of the constant, here `"RED"`. +5. Calls a method on an enum constant. 6. Calls a method via enum class name. +7. The RGB values of `RED` and `YELLOW` share first bits (`FF`) so this prints 'true'. diff --git a/examples/03_special_classes/03_Sealed Classes.md b/examples/03_special_classes/03_Sealed Classes.md index 60927a57..f6594779 100755 --- a/examples/03_special_classes/03_Sealed Classes.md +++ b/examples/03_special_classes/03_Sealed Classes.md @@ -1,10 +1,8 @@ # Sealed Classes -[Sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) let you restrict the use of inheritance. Once you declare a class sealed, nobody else can create its subclasses. +[Sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) let you restrict the use of inheritance. Once you declare a class sealed, it can only be subclassed from inside the same package where the sealed class is declared. It cannot be subclassed outside of the package where the sealed class is declared. -
- -```kotlin +```run-kotlin sealed class Mammal(val name: String) // 1 class Cat(val catName: String) : Mammal(catName) // 2 @@ -22,11 +20,8 @@ fun main() { } ``` -
- - 1. Defines a sealed class. -2. Defines subclasses. Note that all subclasses must be in the same file. +2. Defines subclasses. Note that all subclasses must be in the same package. 3. Uses an instance of the sealed class as an argument in a `when` expression. 4. A smartcast is performed, casting `Mammal` to `Human`. 5. A smartcast is performed, casting `Mammal` to `Cat`. diff --git a/examples/03_special_classes/04_Object.md b/examples/03_special_classes/04_Object.md index 6e14d8eb..f2b10352 100755 --- a/examples/03_special_classes/04_Object.md +++ b/examples/03_special_classes/04_Object.md @@ -2,9 +2,7 @@ Classes and objects in Kotlin work the same way as in most object-oriented languages: a *class* is a blueprint, and an *object* is an instance of a class. Usually, you define a class and then create multiple instances of that class: -
- -```kotlin +```run-kotlin import java.util.Random class LuckDispatcher { //1 @@ -23,8 +21,6 @@ fun main() { } ``` -
- 1. Defines a blueprint. 2. Defines a method. 3. Creates instances. @@ -44,9 +40,7 @@ Here is a basic typical usage of an `object` **expression**: a simple object/pro There is no need to do so in class declaration: you create a single object, declare its members and access it within one function. Objects like this are often created in Java as anonymous class instances. -
- -```kotlin +```run-kotlin fun rentPrice(standardDays: Int, festivityDays: Int, specialDays: Int): Unit { //1 val dayRates = object { //2 @@ -66,8 +60,6 @@ fun main() { } ``` -
- 1. Creates a function with parameters. 2. Creates an object to use when calculating the result value. 3. Accesses the object's properties. @@ -78,11 +70,9 @@ fun main() { You can also use the `object` **declaration**. It isn't an expression, and can't be used in a variable assignment. You should use it to directly access its members: -
- -```kotlin +```run-kotlin object DoAuth { //1 - fun takeParams(username: String, password: String){ //2 + fun takeParams(username: String, password: String) { //2 println("input Auth parameters = $username:$password") } } @@ -93,8 +83,6 @@ fun main(){ ``` -
- 1. Creates an object declaration. 2. Defines the object method. 3. Calls the method. This is when the object is actually created. @@ -105,9 +93,7 @@ An object declaration inside a class defines another useful case: the **companio Syntactically it's similar to the static methods in Java: you call object members using its *class name* as a qualifier. If you plan to use a companion object in Kotlin, consider using a *package-level* function instead. -
- -```kotlin +```run-kotlin class BigBen { //1 companion object Bonger { //2 fun getBongs(nTimes: Int) { //3 @@ -123,8 +109,6 @@ fun main() { } ``` -
- 1. Defines a class. 2. Defines a companion. Its name can be omitted. 3. Defines a companion object method. diff --git a/examples/04_functional/01_Higher-Order Functions.md b/examples/04_functional/01_Higher-Order Functions.md index d9c64889..640a6166 100755 --- a/examples/04_functional/01_Higher-Order Functions.md +++ b/examples/04_functional/01_Higher-Order Functions.md @@ -4,9 +4,7 @@ A [*higher-order function*](https://kotlinlang.org/docs/reference/lambdas.html) ### Taking Functions as Parameters -
- -```kotlin +```run-kotlin fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int { // 1 return operation(x, y) // 2 } @@ -20,19 +18,15 @@ fun main() { } ``` -
- 1. Declares a higher-order function. It takes two integer parameters, `x` and `y`. Additionally, it takes another function `operation` as a parameter. The `operation` parameters and return type are also defined in the declaration. -2. The higher order function returns the result of `operation` invocation with the supplied agruments. +2. The higher order function returns the result of `operation` invocation with the supplied arguments. 3. Declares a function that matches the `operation`signature. 4. Invokes the higher-order function passing in two integer values and the function argument `::sum`. `::` is the notation that references a function by name in Kotlin. 5. Invokes the higher-order function passing in a lambda as a function argument. Looks clearer, doesn't it? ### Returning Functions -
- -```kotlin +```run-kotlin fun operation(): (Int) -> Int { // 1 return ::square } @@ -45,10 +39,7 @@ fun main() { } ``` -
- -1. Declares a higher-order function that returns a function. +1. Declares a higher-order function that returns a function. `(Int) -> Int` represents the parameters and return type of the `square` function. 2. Declares a function matching the signature. 3. Invokes `operation` to get the result assigned to a variable. Here `func` becomes `square` which is returned by `operation`. 4. Invokes `func`. The `square` function is actually executed. - diff --git a/examples/04_functional/02_Lambdas.md b/examples/04_functional/02_Lambdas.md index 2868abb8..13acd332 100755 --- a/examples/04_functional/02_Lambdas.md +++ b/examples/04_functional/02_Lambdas.md @@ -2,28 +2,26 @@ [*Lambda functions*](https://kotlinlang.org/docs/reference/lambdas.html) ("lambdas") are a simple way to create functions ad-hoc. Lambdas can be denoted very concisely in many cases thanks to type inference and the implicit `it` variable. -
- -```kotlin +```run-kotlin fun main() { //sampleStart // All examples create a function object that performs upper-casing. // So it's a function from String to String - val upperCase1: (String) -> String = { str: String -> str.toUpperCase() } // 1 + val upperCase1: (String) -> String = { str: String -> str.uppercase() } // 1 - val upperCase2: (String) -> String = { str -> str.toUpperCase() } // 2 + val upperCase2: (String) -> String = { str -> str.uppercase() } // 2 - val upperCase3 = { str: String -> str.toUpperCase() } // 3 + val upperCase3 = { str: String -> str.uppercase() } // 3 - // val upperCase4 = { str -> str.toUpperCase() } // 4 + // val upperCase4 = { str -> str.uppercase() } // 4 - val upperCase5: (String) -> String = { it.toUpperCase() } // 5 + val upperCase5: (String) -> String = { it.uppercase() } // 5 - val upperCase6: (String) -> String = String::toUpperCase // 6 + val upperCase6: (String) -> String = String::uppercase // 6 - println(upperCase2("hello")) println(upperCase1("hello")) + println(upperCase2("hello")) println(upperCase3("hello")) println(upperCase5("hello")) println(upperCase6("hello")) @@ -31,8 +29,6 @@ fun main() { } ``` -
- 1. A lambda in all its glory, with explicit types everywhere. The lambda is the part in curly braces, which is assigned to a variable of type `(String) -> String` (a function type). 2. Type inference inside lambda: the type of the lambda parameter is inferred from the type of the variable it's assigned to. 3. Type inference outside lambda: the type of the variable is inferred from the type of the lambda parameter and return value. diff --git a/examples/04_functional/03_extensionFunctions.md b/examples/04_functional/03_extensionFunctions.md index 66020160..3bbde43a 100755 --- a/examples/04_functional/03_extensionFunctions.md +++ b/examples/04_functional/03_extensionFunctions.md @@ -2,32 +2,28 @@ Kotlin lets you add new members to any class with the [extensions](https://kotlinlang.org/docs/reference/extensions.html) mechanism. Namely, there are two types of extensions: extension functions and extension properties. They look a lot like normal functions and properties but with one important difference: you need to specify the type that you extend. -
- -```kotlin -data class Item(val name: String, val price: Float) // 1 +```run-kotlin +data class Item(val name: String, val price: Float) // 1 data class Order(val items: Collection) -fun Order.maxPricedItemValue(): Float = this.items.maxBy { it.price }?.price ?: 0F // 2 -fun Order.maxPricedItemName() = this.items.maxBy { it.price }?.name ?: "NO_PRODUCTS" +fun Order.maxPricedItemValue(): Float = this.items.maxByOrNull { it.price }?.price ?: 0F // 2 +fun Order.maxPricedItemName() = this.items.maxByOrNull { it.price }?.name ?: "NO_PRODUCTS" -val Order.commaDelimitedItemNames: String // 3 +val Order.commaDelimitedItemNames: String // 3 get() = items.map { it.name }.joinToString() fun main() { val order = Order(listOf(Item("Bread", 25.0F), Item("Wine", 29.0F), Item("Water", 12.0F))) - println("Max priced item name: ${order.maxPricedItemName()}") // 4 + println("Max priced item name: ${order.maxPricedItemName()}") // 4 println("Max priced item value: ${order.maxPricedItemValue()}") - println("Items: ${order.commaDelimitedItemNames}") // 5 + println("Items: ${order.commaDelimitedItemNames}") // 5 } ``` -
- 1. Defines simple models of `Item` and `Order`. `Order` can contain a collection of `Item` objects. 2. Adds extension functions for the `Order` type. 3. Adds an extension property for the `Order` type. @@ -35,10 +31,8 @@ fun main() { 5. Accesses the extension property on an instance of `Order`. It is even possible to execute extensions on `null` references. In an extension function, you can check the object for `null` and use the result in your code: - -
-```kotlin +```run-kotlin //sampleStart fun T?.nullSafeToString() = this?.toString() ?: "NULL" // 1 //sampleEnd @@ -47,5 +41,3 @@ fun main() { println("Kotlin".nullSafeToString()) } ``` - -
diff --git a/examples/05_Collections/01_List.md b/examples/05_Collections/01_List.md index 85d6ac3c..362d4d10 100644 --- a/examples/05_Collections/01_List.md +++ b/examples/05_Collections/01_List.md @@ -2,13 +2,11 @@ A [list](https://kotlinlang.org/docs/reference/collections.html) is an ordered collection of items. In Kotlin, lists can be either mutable (`MutableList`) or read-only (`List`). For list creation, use the standard library functions `listOf()` for read-only lists and `mutableListOf()` for mutable lists. To prevent unwanted modifications, obtain read-only views of mutable lists by casting them to `List`. -
- -```kotlin +```run-kotlin val systemUsers: MutableList = mutableListOf(1, 2, 3) // 1 val sudoers: List = systemUsers // 2 -fun addSudoer(newUser: Int) { // 3 +fun addSystemUser(newUser: Int) { // 3 systemUsers.add(newUser) } @@ -17,18 +15,15 @@ fun getSysSudoers(): List { // 4 } fun main() { - addSudoer(4) // 5 + addSystemUser(4) // 5 println("Tot sudoers: ${getSysSudoers().size}") // 6 - getSysSudoers().forEach{ // 7 + getSysSudoers().forEach { // 7 i -> println("Some useful info on user $i") } // getSysSudoers().add(5) <- Error! // 8 } ``` -
- - 1. Creates a `MutableList`. 2. Creates a read-only view of the list. 3. Adds a new item to the `MutableList`. diff --git a/examples/05_Collections/02_Set.md b/examples/05_Collections/02_Set.md index 6ab6a6d0..decd2b44 100644 --- a/examples/05_Collections/02_Set.md +++ b/examples/05_Collections/02_Set.md @@ -2,9 +2,7 @@ A [set](https://kotlinlang.org/docs/reference/collections.html) is an unordered collection that does not support duplicates. For creating sets, there are functions `setOf()` and `mutableSetOf()`. A read-only view of a mutable set can be obtained by casting it to `Set`. -
- -```kotlin +```run-kotlin val openIssues: MutableSet = mutableSetOf("uniqueDescr1", "uniqueDescr2", "uniqueDescr3") // 1 fun addIssue(uniqueDesc: String): Boolean { @@ -24,9 +22,7 @@ fun main() { } ``` -
- -1. Adds an element to the `Set`. +1. Creates a `Set` with given elements. 2. Returns a boolean value showing if the element was actually added. 3. Returns a string, based on function input parameter. 4. Prints a success message: the new element is added to the `Set`. diff --git a/examples/05_Collections/03_Map.md b/examples/05_Collections/03_Map.md index 8a66c25e..d2f6908b 100644 --- a/examples/05_Collections/03_Map.md +++ b/examples/05_Collections/03_Map.md @@ -1,10 +1,8 @@ # Map -A [map](https://kotlinlang.org/docs/reference/collections.html) is a collection of key/value pairs, where each key is unique and is used to retrieve the corresponding value. For creating maps, there are functions `mapOf()` and `mutableMapOf()`. A read-only view of a mutable map can be obtained by casting it to `Map`. +A [map](https://kotlinlang.org/docs/reference/collections.html) is a collection of key/value pairs, where each key is unique and is used to retrieve the corresponding value. For creating maps, there are functions `mapOf()` and `mutableMapOf()`. Using the [to](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/to.html) infix function makes initialization less noisy. A read-only view of a mutable map can be obtained by casting it to `Map`. -
- -```kotlin +```run-kotlin const val POINTS_X_PASS: Int = 15 val EZPassAccounts: MutableMap = mutableMapOf(1 to 100, 2 to 100, 3 to 100) // 1 val EZPassReport: Map = EZPassAccounts // 2 @@ -20,7 +18,7 @@ fun updatePointsCredit(accountId: Int) { fun accountsReport() { println("EZ-Pass report:") - EZPassReport.forEach{ // 5 + EZPassReport.forEach { // 5 k, v -> println("ID $k: credit $v") } } @@ -34,8 +32,6 @@ fun main() { } ``` -
- 1. Creates a mutable `Map`. 2. Creates a read-only view of the `Map`. 3. Checks if the `Map`'s key exists. @@ -44,4 +40,4 @@ fun main() { 6. Reads the account points balance, before updates. 7. Updates an existing account two times. 8. Tries to update a non-existing account: prints an error message. -9. Reads the account points balance, after updates. \ No newline at end of file +9. Reads the account points balance, after updates. diff --git a/examples/05_Collections/04_filter.md b/examples/05_Collections/04_filter.md index de7121b0..978bf5cd 100755 --- a/examples/05_Collections/04_filter.md +++ b/examples/05_Collections/04_filter.md @@ -2,9 +2,7 @@ *filter* function enables you to filter collections. It takes a filter predicate as a lambda-parameter. The predicate is applied to each element. Elements that make the predicate `true` are returned in the result collection. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -21,8 +19,6 @@ fun main() { } ``` -
- 1. Defines collection of numbers. 2. Gets positive numbers. 3. Uses the shorter `it` notation to get negative numbers. diff --git a/examples/05_Collections/04_map.md b/examples/05_Collections/04_map.md index 00d48c2f..825bad1f 100755 --- a/examples/05_Collections/04_map.md +++ b/examples/05_Collections/04_map.md @@ -2,9 +2,7 @@ *map* extension function enables you to apply a transformation to all elements in a collection. It takes a transformer function as a lambda-parameter. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -21,8 +19,6 @@ fun main() { } ``` -
- 1. Defines a collection of numbers. 2. Doubles numbers. 3. Uses the shorter `it` notation to triple the numbers. diff --git a/examples/05_Collections/05_existential.md b/examples/05_Collections/05_existential.md index 970386ae..d685dcc3 100755 --- a/examples/05_Collections/05_existential.md +++ b/examples/05_Collections/05_existential.md @@ -6,9 +6,7 @@ These functions check the existence of collection elements that match a given pr Function `any` returns `true` if the collection contains **at least one** element that matches the given predicate. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -25,8 +23,6 @@ fun main() { } ``` -
- 1. Defines a collection of numbers. 2. Checks if there are negative elements. 3. Checks if there are elements greater than `6`. @@ -36,9 +32,7 @@ fun main() { Function `all` returns `true` if **all** elements in collection match the given predicate. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -55,8 +49,6 @@ fun main() { } ``` -
- 1. Defines a collection of numbers. 2. Checks whether all elements are even. 3. Checks whether all elements are less than `6`. @@ -66,9 +58,7 @@ fun main() { Function `none` returns `true` if there are **no** elements that match the given predicate in the collection. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -85,8 +75,6 @@ fun main() { } ``` -
- 1. Defines a collection of numbers. 2. Checks if there are no odd elements (all elements are even). 3. Checks if there are no elements greater than 6. diff --git a/examples/05_Collections/06_find.md b/examples/05_Collections/06_find.md index 154d1be4..b0043ec9 100755 --- a/examples/05_Collections/06_find.md +++ b/examples/05_Collections/06_find.md @@ -1,11 +1,9 @@ # find, findLast -`find` and `findLast` functions return the first or the last collection element that matches the given predicate. If there are no such elements, functions return `null`. +The `find` and `findLast` functions return the first or the last collection element that matches the given predicate. If there are no such elements, these functions return `null`. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -23,8 +21,6 @@ fun main() { } ``` -
- 1. Defines a collection of words. 2. Looks for the first word starting with "some". 3. Looks for the last word starting with "some". diff --git a/examples/05_Collections/07_firstlast.md b/examples/05_Collections/07_firstlast.md index a83b1aea..bf3b7853 100755 --- a/examples/05_Collections/07_firstlast.md +++ b/examples/05_Collections/07_firstlast.md @@ -6,9 +6,7 @@ These functions return the first and the last element of the collection correspo If a collection is empty or doesn't contain elements matching the predicate, the functions throw `NoSuchElementException`. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -26,8 +24,6 @@ fun main() { } ``` -
- 1. Defines a collection of numbers. 2. Picks the first element. 3. Picks the last element. @@ -38,9 +34,7 @@ fun main() { These functions work almost the same way with one difference: they return `null` if there are no matching elements. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -56,14 +50,12 @@ fun main() { val lastZ = words.lastOrNull { it.endsWith('z') } // 8 //sampleEnd - println("First $first, last $last") - println("First starts with 'f' is $firstF, last starts with 'z' is $firstZ") - println("First ends with 'f' is $lastF, last ends with 'z' is $lastZ") + println("Empty list: first is $first, last is $last") + println("Word list: first item starting with 'f' is $firstF, first item starting with 'z' is $firstZ") + println("Word list: last item ending with 'f' is $lastF, last item ending with 'z' is $lastZ") } ``` -
- 1. Defines a collection of words. 2. Defines an empty collection. 3. Picks the first element from empty collection. It supposed to be `null`. diff --git a/examples/05_Collections/08_count.md b/examples/05_Collections/08_count.md index daa6875e..ee0792d1 100755 --- a/examples/05_Collections/08_count.md +++ b/examples/05_Collections/08_count.md @@ -2,9 +2,7 @@ `count` functions returns either the total number of elements in a collection or the number of elements matching the given predicate. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -19,8 +17,6 @@ fun main() { } ``` -
- 1. Defines a collection of numbers. 2. Counts the total number of elements. 3. Counts the number of even elements. diff --git a/examples/05_Collections/10_associateBy.md b/examples/05_Collections/10_associateBy.md index f723f557..df022083 100755 --- a/examples/05_Collections/10_associateBy.md +++ b/examples/05_Collections/10_associateBy.md @@ -4,14 +4,13 @@ Functions `associateBy` and `groupBy` build maps from the elements of a collecti You can also specify an optional `valueSelector` to define what will be stored in the `value` of the map element. The difference between `associateBy` and `groupBy` is how they process objects with the same key: + * `associateBy` uses the last suitable element as the value. * `groupBy` builds a list of all suitable elements and puts it in the value. The returned map preserves the entry iteration order of the original collection. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -27,6 +26,7 @@ fun main() { val phoneBook = people.associateBy { it.phone } // 3 val cityBook = people.associateBy(Person::phone, Person::city) // 4 val peopleCities = people.groupBy(Person::city, Person::name) // 5 + val lastPersonCity = people.associateBy(Person::city, Person::name) // 6 //sampleEnd @@ -34,13 +34,13 @@ fun main() { println("Phone book: $phoneBook") println("City book: $cityBook") println("People living in each city: $peopleCities") + println("Last person living in each city: $lastPersonCity") } ``` -
- 1. Defines a data class that describes a person. 2. Defines a collection of people. 3. Builds a map from phone numbers to their owners' information. `it.phone` is the `keySelector` here. The `valueSelector` is not provided, so the values of the map are `Person` objects themselves. 4. Builds a map from phone numbers to the cities where owners live. `Person::city` is the `valueSelector` here, so the values of the map contain only cities. 5. Builds a map that contains cities and people living there. The values of the map are lists of person names. +6. Builds a map that contains cities and the last person living there. The values of the map are names of the last person living in each city. diff --git a/examples/05_Collections/11_partition.md b/examples/05_Collections/11_partition.md index 27db074a..c2877a0c 100755 --- a/examples/05_Collections/11_partition.md +++ b/examples/05_Collections/11_partition.md @@ -1,12 +1,11 @@ # partition -`partition` function splits the original collection into pair of lists using a given predicate: - * Elements for which the predicate is `true`. - * Elements for which the predicate is `false`. +The `partition` function splits the original collection into a pair of lists using a given predicate: -
+ 1. Elements for which the predicate is `true`. + 1. Elements for which the predicate is `false`. -```kotlin +```run-kotlin fun main() { //sampleStart @@ -25,8 +24,6 @@ fun main() { ``` -
- 1. Defines a collection of numbers. 2. Splits `numbers` into a `Pair` of lists with even and odd numbers. 3. Splits `numbers` into two lists with positive and negative numbers. Pair destructuring is applied here to get the `Pair` members. diff --git a/examples/05_Collections/12_flatMap.md b/examples/05_Collections/12_flatMap.md index d6cd158f..8d4286dd 100755 --- a/examples/05_Collections/12_flatMap.md +++ b/examples/05_Collections/12_flatMap.md @@ -2,23 +2,24 @@ `flatMap` transforms each element of a collection into an iterable object and builds a single list of the transformation results. The transformation is user-defined. -
- -```kotlin +```run-kotlin fun main() { //sampleStart - val numbers = listOf(1, 2, 3) // 1 - - val tripled = numbers.flatMap { listOf(it, it, it) } // 2 + val fruitsBag = listOf("apple","orange","banana","grapes") // 1 + val clothesBag = listOf("shirts","pants","jeans") // 2 + val cart = listOf(fruitsBag, clothesBag) // 3 + val mapBag = cart.map { it } // 4 + val flatMapBag = cart.flatMap { it } // 5 //sampleEnd - println("Numbers: $numbers") - println("Transformed: $tripled") + println("Your bags are: $mapBag") + println("The things you bought are: $flatMapBag") } ``` -
- -1. Defines a collection of numbers. -2. Builds a list in which every collection element is repeated three times. Important thing is that it's **not** a list of lists; it's a list of integers with nine elements. +1. Defines a collection of Strings with fruit names. +2. Defines a collection of Strings with clothes names. +3. Adds `fruitsBag` and `clothesBag` to the `cart` list. +4. Builds a `map` of `cart` elements, which is a list of two lists. +5. Builds a `flatMap` of `cart` elements, which is a single list consisting of elements from both lists. \ No newline at end of file diff --git a/examples/05_Collections/13_max.md b/examples/05_Collections/13_max.md index 85dcf08c..7a5d5bc6 100755 --- a/examples/05_Collections/13_max.md +++ b/examples/05_Collections/13_max.md @@ -1,23 +1,22 @@ -# min, max +# minOrNull, maxOrNull -`min` and `max` functions return the smallest and the largest element of a collection. If the collection is empty, they return `null`. +`minOrNull` and `maxOrNull` functions return the smallest and the largest element of a collection. If the collection is empty, they return `null`. -
- -```kotlin +```run-kotlin fun main() { //sampleStart val numbers = listOf(1, 2, 3) val empty = emptyList() + val only = listOf(3) - println("Numbers: $numbers, min = ${numbers.min()} max = ${numbers.max()}") // 1 - println("Empty: $empty, min = ${empty.min()}, max = ${empty.max()}") // 2 + println("Numbers: $numbers, min = ${numbers.minOrNull()} max = ${numbers.maxOrNull()}") // 1 + println("Empty: $empty, min = ${empty.minOrNull()}, max = ${empty.maxOrNull()}") // 2 + println("Only: $only, min = ${only.minOrNull()}, max = ${only.maxOrNull()}") // 3 //sampleEnd } ``` -
- -1. For non-empty collection functions return the smallest and the largest element. -2. For empty collections both functions return `null`. +1. For non-empty collection, functions return the smallest and the largest element. +2. For empty collections, both functions return `null`. +3. For collection with only one element, both functions return the same value. diff --git a/examples/05_Collections/14_sorted.md b/examples/05_Collections/14_sorted.md index 22d6dc71..d1bfda2c 100755 --- a/examples/05_Collections/14_sorted.md +++ b/examples/05_Collections/14_sorted.md @@ -4,25 +4,29 @@ `sortedBy` sorts elements according to natural sort order of the values returned by specified selector function. -
+```run-kotlin +import kotlin.math.abs -```kotlin fun main() { //sampleStart - val shuffled = listOf(5, 4, 2, 1, 3) // 1 - val natural = shuffled.sorted() // 2 - val inverted = shuffled.sortedBy { -it } // 3 + val shuffled = listOf(5, 4, 2, 1, 3, -10) // 1 + val natural = shuffled.sorted() // 2 + val inverted = shuffled.sortedBy { -it } // 3 + val descending = shuffled.sortedDescending() // 4 + val descendingBy = shuffled.sortedByDescending { abs(it) } // 5 //sampleEnd println("Shuffled: $shuffled") println("Natural order: $natural") println("Inverted natural order: $inverted") + println("Inverted natural order value: $descending") + println("Inverted natural order of absolute values: $descendingBy") } ``` -
- 1. Defines a collection of shuffled numbers. 2. Sorts it in the natural order. -2. Sorts it in the inverted natural order by using `-it` as a selector function. +3. Sorts it in the inverted natural order by using `-it` as a selector function. +4. Sorts it in the inverted natural order by using `sortedDescending`. +5. Sorts it in the inverted natural order of items' absolute values by using `abs(it)` as a selector function. diff --git a/examples/05_Collections/15_Map_getValue.md b/examples/05_Collections/15_Map_getValue.md index 7fd8b107..6f2051e1 100644 --- a/examples/05_Collections/15_Map_getValue.md +++ b/examples/05_Collections/15_Map_getValue.md @@ -5,9 +5,7 @@ When applied to a map, `[]` operator returns the value corresponding to the give `getValue` function returns an existing value corresponding to the given key or throws an exception if the key wasn't found. For maps created with `withDefault`, `getValue` returns the default value instead of throwing an exception. -
- -```kotlin +```run-kotlin fun main(args: Array) { //sampleStart @@ -23,8 +21,7 @@ fun main(args: Array) { try { map.getValue("anotherKey") // 4 - } - catch (e: NoSuchElementException) { + } catch (e: NoSuchElementException) { println("Message: $e") } @@ -37,8 +34,6 @@ fun main(args: Array) { } ``` -
- 1. Returns 42 because it's the value corresponding to the key `"key"`. 2. Returns `null` because `"key2"` is not in the map. 3. Returns the default value because `"key2"` is absent. For this key it's 4. diff --git a/examples/05_Collections/16_zip.md b/examples/05_Collections/16_zip.md index 3fd1b6f2..5b8297be 100755 --- a/examples/05_Collections/16_zip.md +++ b/examples/05_Collections/16_zip.md @@ -1,12 +1,10 @@ # zip -`zip` function merges two given collections into a new collection. By default, the result collection contains `Pairs` of source collection elements with the same index. However, you can define own structure of the result collection element. +`zip` function merges two given collections into a new collection. By default, the result collection contains `Pairs` of source collection elements with the same index. However, you can define your own structure of the result collection element. -The size of the result collection equals to the minumum size of a source collection. +The size of the result collection equals to the minimum size of a source collection. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -22,8 +20,6 @@ fun main() { } ``` -
- 1. Defines two collections. 2. Merges them into a list of pairs. The infix notation is used here. 3. Merges them into a list of String values by the given transformation. diff --git a/examples/05_Collections/17_getOrElse.md b/examples/05_Collections/17_getOrElse.md index ec22078d..919bbed6 100644 --- a/examples/05_Collections/17_getOrElse.md +++ b/examples/05_Collections/17_getOrElse.md @@ -3,10 +3,7 @@ `getOrElse` provides safe access to elements of a collection. It takes an index and a function that provides the default value in cases when the index is out of bound. - -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -17,16 +14,12 @@ fun main() { } ``` -
- 1. Prints the element at the index `1`. 2. Prints `42` because the index `10` is out of bounds. `getOrElse` can also be applied to `Map` to get the value for the given key. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -42,8 +35,6 @@ fun main() { } ``` -
- 1. Prints the default value because the key `"x"` is not in the map. 2. Prints `3`, the value for the key `"x"`. 3. Prints the default value because the value for the key `"x"` is not defined. diff --git a/examples/06_scope_functions/01_let.md b/examples/06_scope_functions/01_let.md index ba5a638c..118427c1 100644 --- a/examples/06_scope_functions/01_let.md +++ b/examples/06_scope_functions/01_let.md @@ -1,13 +1,11 @@ # let The Kotlin standard library function `let` can be used for scoping and null-checks. When called on an object, `let` executes the given block of code and returns the result of its last expression. -The object is accessible inside the block by the reference `it`. +The object is accessible inside the block by the reference `it` (by default) or a custom name. -
- -```kotlin +```run-kotlin fun customPrint(s: String) { - print(s.toUpperCase()) + print(s.uppercase()) } fun main() { @@ -28,15 +26,26 @@ fun main() { println() } } + + fun printIfBothNonNull(strOne: String?, strTwo: String?) { + strOne?.let { firstString -> // 5 + strTwo?.let { secondString -> + customPrint("$firstString : $secondString") + println() + } + } + } + printNonNull(null) printNonNull("my string") + printIfBothNonNull("First","Second") //sampleEnd } -``` -
+``` 1. Calls the given block on the result on the string "_test_". 2. Calls the function on "_test_" by the `it` reference. 3. `let` returns the value of this expression. -4. Uses safe call, so `let` and its code block will be executed only on non-null values. +4. Uses safe call, so `let` and its code block will be executed only on non-null values. +5. Uses the custom name instead of `it`, so that the nested `let` can access the context object of the outer `let`. diff --git a/examples/06_scope_functions/02_run.md b/examples/06_scope_functions/02_run.md index 227fc06e..068eb733 100644 --- a/examples/06_scope_functions/02_run.md +++ b/examples/06_scope_functions/02_run.md @@ -1,11 +1,9 @@ # run Like [`let`](01_let), `run` is another scoping function from the standard library. Basically, it does the same: executes a code block and returns its result. -The difference is that inside `run` the object is accessed by `this`. This is useful when you want to call the object's methods rather than pass it as an argument.
+The difference is that inside `run` the object is accessed by `this`. This is useful when you want to call the object's methods rather than pass it as an argument. -
- -```kotlin +```run-kotlin fun main() { //sampleStart @@ -24,9 +22,6 @@ fun main() { } ``` -
- - 1. Calls the given block on a nullable variable. 2. Inside `run`, the object's members are accessed without its name. 3. `run` returns the `length` of the given `String` if it's not `null`. diff --git a/examples/06_scope_functions/03_with.md b/examples/06_scope_functions/03_with.md index d4e2b0cb..34577990 100644 --- a/examples/06_scope_functions/03_with.md +++ b/examples/06_scope_functions/03_with.md @@ -4,9 +4,7 @@ `with` is a non-extension function that can access members of its argument concisely: you can omit the instance name when referring to its members. -
- -```kotlin +```run-kotlin class Configuration(var host: String, var port: Int) fun main() { @@ -22,5 +20,3 @@ fun main() { //sampleEnd } ``` - -
diff --git a/examples/06_scope_functions/04_apply.md b/examples/06_scope_functions/04_apply.md index 500346e7..a59f1d03 100644 --- a/examples/06_scope_functions/04_apply.md +++ b/examples/06_scope_functions/04_apply.md @@ -3,9 +3,7 @@ `apply` executes a block of code on an object and returns the object itself. Inside the block, the object is referenced by `this`. This function is handy for initializing objects. -
- -```kotlin +```run-kotlin data class Person(var name: String, var age: Int, var about: String) { constructor() : this("", 0, "") } @@ -23,8 +21,6 @@ fun main() { } ``` -
- 1. Creates a `Person()` instance with default property values. 2. Applies the code block (next 3 lines) to the instance. diff --git a/examples/06_scope_functions/05_also.md b/examples/06_scope_functions/05_also.md index d34e61ef..1802b8bd 100644 --- a/examples/06_scope_functions/05_also.md +++ b/examples/06_scope_functions/05_also.md @@ -4,9 +4,7 @@ Inside the block, the object is referenced by `it`, so it's easier to pass it as an argument. This function is handy for embedding additional actions, such as logging in call chains. -
- -```kotlin +```run-kotlin data class Person(var name: String, var age: Int, var about: String) { constructor() : this("", 0, "") } @@ -25,8 +23,6 @@ fun main() { } ``` -
- 1. Creates a `Person()` object with the given property values. 2. Applies the given code block to the object. The return value is the object itself. 3. Calls the logging function passing the object as an argument. diff --git a/examples/07_Delegation/01_delegationPattern.md b/examples/07_Delegation/01_delegationPattern.md index 30e0307c..9f396da2 100755 --- a/examples/07_Delegation/01_delegationPattern.md +++ b/examples/07_Delegation/01_delegationPattern.md @@ -2,37 +2,33 @@ Kotlin supports easy implementation of the [delegation pattern](https://kotlinlang.org/docs/reference/delegation.html) on the native level without any boilerplate code. -
- -```kotlin +```run-kotlin interface SoundBehavior { // 1 fun makeSound() } -class ScreamBehavior(val n:String): SoundBehavior { // 2 - override fun makeSound() = println("${n.toUpperCase()} !!!") +class ScreamBehavior(val n: String): SoundBehavior { // 2 + override fun makeSound() = println("${n.uppercase()} !!!") } -class RockAndRollBehavior(val n:String): SoundBehavior { // 2 +class RockAndRollBehavior(val n: String): SoundBehavior { // 2 override fun makeSound() = println("I'm The King of Rock 'N' Roll: $n") } // Tom Araya is the "singer" of Slayer -class TomAraya(n:String): SoundBehavior by ScreamBehavior(n) // 3 +class TomAraya(n: String): SoundBehavior by ScreamBehavior(n) // 3 // You should know ;) -class ElvisPresley(n:String): SoundBehavior by RockAndRollBehavior(n) // 3 +class ElvisPresley(n: String): SoundBehavior by RockAndRollBehavior(n) // 3 fun main() { - val tomAraya = TomAraya("Trash Metal") - tomAraya.makeSound() // 4 + val tomAraya = TomAraya("Thrash Metal") + tomAraya.makeSound() // 4 val elvisPresley = ElvisPresley("Dancin' to the Jailhouse Rock.") elvisPresley.makeSound() } ``` -
- 1. Defines the interface `SoundBehavior` with one method. 2. The classes `ScreamBehavior` and `RockAndRollBehavior` implement the interface and contain their own implementations of the method. diff --git a/examples/07_Delegation/02_DelegatedProperties.md b/examples/07_Delegation/02_DelegatedProperties.md index c8864f57..0c9f584c 100755 --- a/examples/07_Delegation/02_DelegatedProperties.md +++ b/examples/07_Delegation/02_DelegatedProperties.md @@ -3,9 +3,7 @@ Kotlin provides a mechanism of [delegated properties](http://kotlinlang.org/docs/reference/delegated-properties.html) that allows delegating the calls of the property `set` and `get` methods to a certain object. The delegate object in this case should have the method `getValue`. For mutable properties, you'll also need `setValue`. -
- -```kotlin +```run-kotlin import kotlin.reflect.KProperty class Example { @@ -31,19 +29,15 @@ fun main() { } ``` -
- 1. Delegates property `p` of type `String` to the instance of class `Delegate`. The delegate object is defined after the `by` keyword. 2. Delegation methods. The signatures of these methods are always as shown in the example. Implementations may contain any steps you need. For immutable properties only `getValue` is required. ### Standard Delegates -The Kotlin standard library contains a bunch of useful delegates, like `lazy`, `observable`, and other. You may use them as is. +The Kotlin standard library contains a bunch of useful delegates, like `lazy`, `observable`, and others. You may use them as is. For example `lazy`is used for lazy initialization. -
- -```kotlin +```run-kotlin class LazySample { init { println("created!") // 1 @@ -62,22 +56,18 @@ fun main() { } ``` -
- 1. Property `lazy` is not initialized on object creation. 2. The first call to `get()` executes the lambda expression passed to `lazy()` as an argument and saves the result. 3. Further calls to `get()` return the saved result. -If you want thread safety, use `blockingLazy()` instead: it guarantees that the values will be computed only in one thread and that all threads will see the same value. + If you want thread safety, use `blockingLazy()` instead: it guarantees that the values will be computed only in one thread and that all threads will see the same value. ### Storing Properties in a Map Property delegation can be used for storing properties in a map. This is handy for tasks like parsing JSON or doing other "dynamic" stuff. -
- -```kotlin +```run-kotlin class User(val map: Map) { val name: String by map // 1 val age: Int by map // 1 @@ -93,8 +83,6 @@ fun main() { } ``` -
- 1. Delegates take values from the `map` by the string keys - names of properties. You can delegate mutable properties to a map as well. In this case, the map will be modified upon property assignments. Note that you will need `MutableMap` instead of read-only `Map`. diff --git a/examples/08_productivity_boosters/01_namedArguments.md b/examples/08_productivity_boosters/01_namedArguments.md index 65de69a0..c6623b12 100755 --- a/examples/08_productivity_boosters/01_namedArguments.md +++ b/examples/08_productivity_boosters/01_namedArguments.md @@ -3,9 +3,7 @@ As with most other programming languages (Java, C++, etc.), Kotlin supports passing arguments to methods and constructors according to the order they are defined. Kotlin also supports [named arguments](https://kotlinlang.org/docs/reference/functions.html#named-arguments) to allow clearer invocations and avoid mistakes with the order of arguments. Such mistakes are hard to find because they are not detected by the compiler, for example, when two sequential arguments have the same type. -
- -```kotlin +```run-kotlin fun format(userName: String, domain: String) = "$userName@$domain" fun main() { @@ -18,8 +16,6 @@ fun main() { } ``` -
- 1. Calls a function with argument values. 2. Calls a function with switched arguments. No syntax errors, but the result _domain.com@username_ is incorrect. 3. Calls a function with named arguments. diff --git a/examples/08_productivity_boosters/02_String Templates.md b/examples/08_productivity_boosters/02_String Templates.md index 847cb671..842e2263 100755 --- a/examples/08_productivity_boosters/02_String Templates.md +++ b/examples/08_productivity_boosters/02_String Templates.md @@ -2,21 +2,17 @@ [String templates](https://kotlinlang.org/docs/reference/basic-types.html#string-templates) allow you to include variable references and expressions into strings. When the value of a string is requested (for example, by `println`), all references and expressions are substituted with actual values. -
- -```kotlin +```run-kotlin fun main() { //sampleStart val greeting = "Kotliner" println("Hello $greeting") // 1 - println("Hello ${greeting.toUpperCase()}") // 2 + println("Hello ${greeting.uppercase()}") // 2 //sampleEnd } ``` -
- 1. Prints a string with a variable reference. References in strings start with `$`. 2. Prints a string with an expression. Expressions start with `$` and are enclosed in curly braces. diff --git a/examples/08_productivity_boosters/03_Destructuring Declarations.md b/examples/08_productivity_boosters/03_Destructuring Declarations.md index e1f1fc7d..10308de3 100755 --- a/examples/08_productivity_boosters/03_Destructuring Declarations.md +++ b/examples/08_productivity_boosters/03_Destructuring Declarations.md @@ -2,9 +2,7 @@ [Destructuring declaration](https://kotlinlang.org/docs/reference/multi-declarations.html#destructuring-declarations) syntax can be very handy, especially when you need an instance only for accessing its members. It lets you define the instance without a specific name therefore saving a few lines of code. -
- -```kotlin +```run-kotlin fun findMinMax(list: List): Pair { // do the math return Pair(50, 100) @@ -25,15 +23,11 @@ fun main() { } ``` -
- 1. Destructures an `Array`. The number of variables on the left side matches the number of arguments on the right side. 2. Maps can be destructured as well. `name` and `age` variables are mapped to the map key and value. 3. Built-in `Pair` and `Triple` types support destructuring too, even as return values from functions. -
- -```kotlin +```run-kotlin data class User(val username: String, val email: String) // 1 fun getUser() = User("Mary", "mary@somewhere.com") @@ -48,16 +42,12 @@ fun main() { } ``` -
- 1. Defines a data class. 2. Destructures an instance. Declared values are mapped to the instance fields. 3. Data class automatically defines the `component1()` and `component2()` methods that will be called during destructuring. 4. Use _underscore_ if you don't need one of the values, avoiding the compiler hint indicating an unused variable. -
- -```kotlin +```run-kotlin class Pair(val first: K, val second: V) { // 1 operator fun component1(): K { return first @@ -75,7 +65,5 @@ fun main() { } ``` -
- 1. Defines a custom `Pair` class with `component1()` and `component2()` methods. 2. Destructures an instance of this class the same way as for built-in `Pair`. diff --git a/examples/08_productivity_boosters/04_Smart Casts.md b/examples/08_productivity_boosters/04_Smart Casts.md index c2d488f4..6a3cf52c 100755 --- a/examples/08_productivity_boosters/04_Smart Casts.md +++ b/examples/08_productivity_boosters/04_Smart Casts.md @@ -2,12 +2,11 @@ The Kotlin compiler is smart enough to perform type casts automatically in most cases, including: + 1. Casts from nullable types to their non-nullable counterparts. 2. Casts from a supertype to a subtype. -
- -```kotlin +```run-kotlin import java.time.LocalDate import java.time.chrono.ChronoLocalDate @@ -36,8 +35,6 @@ fun main() { ``` -
- 1. Declares a nullable variable. 2. Smart-cast to non-nullable (thus allowing direct access to `isLeapYear`). 3. Smart-cast inside a condition (this is possible because, like Java, Kotlin uses [short-circuiting](https://en.wikipedia.org/wiki/Short-circuit_evaluation)). diff --git a/examples/09_Kotlin_JS/01_dynamic.md b/examples/09_Kotlin_JS/01_dynamic.md index 47c66777..d84bc8a7 100755 --- a/examples/09_Kotlin_JS/01_dynamic.md +++ b/examples/09_Kotlin_JS/01_dynamic.md @@ -4,9 +4,7 @@ That is needed in order to interoperate with untyped or loosely typed environments, such as the JavaScript ecosystem. -
- -```kotlin +```run-kotlin-js fun main(){ //sampleStart val a: dynamic = "abc" // 1 @@ -28,8 +26,6 @@ fun main(){ } ``` -
- 1. Any value can be assigned to a `dynamic` variable type. 2. A dynamic value can be assigned to anything. 3. A dynamic variable can be passed as an argument to any function. diff --git a/examples/09_Kotlin_JS/02_js_function.md b/examples/09_Kotlin_JS/02_js_function.md index 678b9d75..798385b4 100755 --- a/examples/09_Kotlin_JS/02_js_function.md +++ b/examples/09_Kotlin_JS/02_js_function.md @@ -4,22 +4,17 @@ You can inline JavaScript code into your Kotlin code using the js("…") functio This should be used with extreme care. -
- -```kotlin +```run-kotlin-js fun main() { -// sampleStart +//sampleStart js("alert(\"alert from Kotlin!\")") // 1 -// sampleEnd +//sampleEnd } ``` -
1. Sending a JavaScript alert from a Kotlin function. -
- -```kotlin +```run-kotlin-js fun main(){ //sampleStart val json = js("{}") // 1 @@ -31,8 +26,6 @@ fun main(){ } ``` -
- 1. Creates a JavaScript object literal. The `js(...)` function return type is `dynamic`. 2. Adds some properties by utilizing the `dynamic` type capabilities. 3. Passes the JSON to JavaScript API. diff --git a/examples/09_Kotlin_JS/03_external.md b/examples/09_Kotlin_JS/03_external.md index c0bd2562..cee6d84a 100755 --- a/examples/09_Kotlin_JS/03_external.md +++ b/examples/09_Kotlin_JS/03_external.md @@ -2,9 +2,7 @@ *external* keyword allows to declare existing JavaScript API in a type-safe way. -
- -```kotlin +```run-kotlin-js external fun alert(msg: String) // 1 fun main() { @@ -12,8 +10,6 @@ fun main() { } ``` -
- 1. Declares an existing JavaScript function `alert` which takes a single `String` argument. 2. Uses `alert` as if it were regular Kotlin. diff --git a/examples/09_Kotlin_JS/05_Canvas.md b/examples/09_Kotlin_JS/05_Canvas.md index 7a369e22..81ad2538 100755 --- a/examples/09_Kotlin_JS/05_Canvas.md +++ b/examples/09_Kotlin_JS/05_Canvas.md @@ -4,15 +4,13 @@ The following example demonstrates usage of HTML5 Canvas from Kotlin. Here strange creatures are watching the kotlin logo. You can drag'n'drop them as well as the logo. Doubleclick to add more creatures but be careful. They may be watching you! -
- -```kotlin +```run-kotlin-canvas package creatures -import jquery.* import org.w3c.dom.* -import kotlin.browser.document -import kotlin.browser.window +import org.w3c.dom.events.MouseEvent +import kotlinx.browser.document +import kotlinx.browser.window import kotlin.math.* @@ -22,9 +20,9 @@ fun getImage(path: String): HTMLImageElement { return image } -val canvas = initalizeCanvas() +val canvas = initializeCanvas() -fun initalizeCanvas(): HTMLCanvasElement { +fun initializeCanvas(): HTMLCanvasElement { val canvas = document.createElement("canvas") as HTMLCanvasElement val context = canvas.getContext("2d") as CanvasRenderingContext2D context.canvas.width = window.innerWidth.toInt() @@ -67,11 +65,11 @@ abstract class Shape() { } } -val logoImage by lazy { getImage("http://try.kotlinlang.org/static/images/kotlin_logo.svg") } +val logoImage by lazy { getImage("https://play.kotlinlang.org/assets/kotlin-logo.svg") } -val logoImageSize = v(120.0, 30.0) +val logoImageSize = v(64.0, 64.0) -val Kotlin = Logo(v(canvas.width / 2.0 - logoImageSize.x / 2.0 - 40, canvas.height / 2.0 - logoImageSize.y / 2.0 - 20)) +val Kotlin = Logo(v(canvas.width / 2.0 - logoImageSize.x / 2.0 - 64, canvas.height / 2.0 - logoImageSize.y / 2.0 - 64)) class Logo(override var pos: Vector) : Shape() { val relSize: Double = 0.18 @@ -89,7 +87,7 @@ class Logo(override var pos: Vector) : Shape() { } size = logoImageSize * (state.size.x / logoImageSize.x) * relSize - state.context.drawImage(getImage("http://try.kotlinlang.org/static/images/kotlin_logo.svg"), 0.0, 0.0, + state.context.drawImage(getImage("https://play.kotlinlang.org/assets/kotlin-logo.svg"), 0.0, 0.0, logoImageSize.x, logoImageSize.y, position.x, position.y, size.x, size.y) @@ -219,10 +217,10 @@ class CanvasState(val canvas: HTMLCanvasElement) { val interval = 1000 / 30 init { - jq(canvas).mousedown { + canvas.onmousedown = { e: MouseEvent -> changed = true selection = null - val mousePos = mousePos(it) + val mousePos = mousePos(e) for (shape in shapes) { if (mousePos in shape) { dragOff = mousePos - shape.pos @@ -233,25 +231,27 @@ class CanvasState(val canvas: HTMLCanvasElement) { } } - jq(canvas).mousemove { + canvas.onmousemove = { e: MouseEvent -> if (selection != null) { - selection!!.pos = mousePos(it) - dragOff + selection!!.pos = mousePos(e) - dragOff changed = true } } - jq(canvas).mouseup { + canvas.onmouseup = { e: MouseEvent -> if (selection != null) { selection!!.selected = false } selection = null changed = true + this } - jq(canvas).dblclick { - val newCreature = Creature(mousePos(it), this@CanvasState) + canvas.ondblclick = { e: MouseEvent -> + val newCreature = Creature(mousePos(e), this@CanvasState) addShape(newCreature) changed = true + this } window.setInterval({ @@ -353,6 +353,3 @@ fun main(args: Array) { //sampleEnd } ``` - -
- diff --git a/examples/09_Kotlin_JS/06_HtmlBuilder.md b/examples/09_Kotlin_JS/06_HtmlBuilder.md index 4c80cd53..4afc44e2 100755 --- a/examples/09_Kotlin_JS/06_HtmlBuilder.md +++ b/examples/09_Kotlin_JS/06_HtmlBuilder.md @@ -4,16 +4,10 @@ Kotlin provides you with an option to describe structured data in a declarative Below is an example of a type-safe Groovy-style builder. In this example, we will describe an HTML page in Kotlin. -
- -```kotlin +```run-kotlin-canvas package html -import org.w3c.dom.* -import kotlin.browser.document -import kotlin.browser.window - -fun main(args: Array) { +fun main() { //sampleStart val result = html { // 1 head { // 2 @@ -27,14 +21,14 @@ fun main(args: Array) { } // an element with attributes and text content - a(href = "http://jetbrains.com/kotlin") { +"Kotlin" } + a(href = "http://kotlinlang.org") { +"Kotlin" } // mixed content p { +"This is some" b { +"mixed" } +"text. For more see the" - a(href = "http://jetbrains.com/kotlin") { + a(href = "http://kotlinlang.org") { +"Kotlin" } +"project" @@ -49,25 +43,61 @@ fun main(args: Array) { } } //sampleEnd + println(result) +} - document.body!!.appendChild(result.element) +interface Element { + fun render(builder: StringBuilder, indent: String) } -abstract class Tag(val name: String) { - val element = document.createElement(name) - protected fun initTag(tag: T, init: T.() -> Unit): T { +class TextElement(val text: String) : Element { + override fun render(builder: StringBuilder, indent: String) { + builder.append("$indent$text\n") + } +} + +@DslMarker +annotation class HtmlTagMarker + +@HtmlTagMarker +abstract class Tag(val name: String) : Element { + val children = arrayListOf() + val attributes = hashMapOf() + + protected fun initTag(tag: T, init: T.() -> Unit): T { tag.init() - element.appendChild(tag.element) + children.add(tag) return tag } + + override fun render(builder: StringBuilder, indent: String) { + builder.append("$indent<$name${renderAttributes()}>\n") + for (c in children) { + c.render(builder, indent + " ") + } + builder.append("$indent\n") + } + + private fun renderAttributes(): String { + val builder = StringBuilder() + for ((attr, value) in attributes) { + builder.append(" $attr=\"$value\"") + } + return builder.toString() + } + + override fun toString(): String { + val builder = StringBuilder() + render(builder, "") + return builder.toString() + } } abstract class TagWithText(name: String) : Tag(name) { operator fun String.unaryPlus() { - element.appendChild(document.createTextNode(this + " ")) + children.add(TextElement(this)) } } - class HTML() : TagWithText("html") { fun head(init: Head.() -> Unit) = initTag(Head(), init) fun body(init: Body.() -> Unit) = initTag(Body(), init) @@ -101,11 +131,11 @@ class LI() : BodyTag("li") class P() : BodyTag("p") class H1() : BodyTag("h1") -class A() : BodyTag("a") { - public var href: String - get() = element.getAttribute("href")!! +class A : BodyTag("a") { + var href: String + get() = attributes["href"]!! set(value) { - element.setAttribute("href", value) + attributes["href"] = value } } @@ -117,8 +147,6 @@ fun html(init: HTML.() -> Unit): HTML { ``` -
- 1. `html` is actually a function call that takes a [lambda expression](http://kotlinlang.org/docs/reference/lambdas.html) as an argument. `html` function takes one parameter which is itself a function. The type of the function is `HTML.() -> Unit`, which is a function type with receiver. @@ -129,4 +157,4 @@ fun html(init: HTML.() -> Unit): HTML { 3. Adds the text to tags by calling the `unaryPlus()` operation, like `+"HTML encoding with Kotlin"`. -For details see: [Type Safe Builders](http://kotlinlang.org/docs/reference/type-safe-builders.html) \ No newline at end of file +For details see: [Type Safe Builders](http://kotlinlang.org/docs/reference/type-safe-builders.html)