From 6f35325ec983167fcaa8d4f0665b55ec0dd18943 Mon Sep 17 00:00:00 2001 From: Pavel Semyonov <42832629+p7nov@users.noreply.github.com> Date: Tue, 5 Feb 2019 17:04:48 +0700 Subject: [PATCH] feat: add scope functions (#70) * docs: added scope functions, renamed chapter stdlib * docs: added scope functions, renamed chapter stdlib * docs: text corrections after proofread --- examples/06_scope_functions/00_description.md | 2 + examples/06_scope_functions/01_let.md | 42 ++++++++++++ examples/06_scope_functions/02_run.md | 32 +++++++++ .../03_with.md} | 4 +- examples/06_scope_functions/04_apply.md | 32 +++++++++ examples/06_scope_functions/05_also.md | 32 +++++++++ examples/06_stdlib/00_description.md | 2 - examples/06_stdlib/01_letFunction.md | 66 ------------------- 8 files changed, 143 insertions(+), 69 deletions(-) create mode 100644 examples/06_scope_functions/00_description.md create mode 100644 examples/06_scope_functions/01_let.md create mode 100644 examples/06_scope_functions/02_run.md rename examples/{06_stdlib/02_withFunction.md => 06_scope_functions/03_with.md} (70%) mode change 100755 => 100644 create mode 100644 examples/06_scope_functions/04_apply.md create mode 100644 examples/06_scope_functions/05_also.md delete mode 100755 examples/06_stdlib/00_description.md delete mode 100755 examples/06_stdlib/01_letFunction.md diff --git a/examples/06_scope_functions/00_description.md b/examples/06_scope_functions/00_description.md new file mode 100644 index 0000000..28304de --- /dev/null +++ b/examples/06_scope_functions/00_description.md @@ -0,0 +1,2 @@ +# Scope Functions + diff --git a/examples/06_scope_functions/01_let.md b/examples/06_scope_functions/01_let.md new file mode 100644 index 0000000..67aa894 --- /dev/null +++ b/examples/06_scope_functions/01_let.md @@ -0,0 +1,42 @@ +# 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`. + +
+ +```kotlin +fun customPrint(s: String) { + print(s.toUpperCase()) +} + +fun main() { +//sampleStart + val empty = "testKotlin".let { // 1 + customPrint(it) // 2 + it.isEmpty() // 3 + } + println(" is empty: $empty") + + + fun printNonNull(str: String?) { + println("Printing \"$str\":") + + str?.let { // 4 + print("\t") + customPrint(it) + println() + } + } + printNonNull(null) + printNonNull("my string") +//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. diff --git a/examples/06_scope_functions/02_run.md b/examples/06_scope_functions/02_run.md new file mode 100644 index 0000000..7279fa9 --- /dev/null +++ b/examples/06_scope_functions/02_run.md @@ -0,0 +1,32 @@ +# run + +Like [`let`](01_let.md), `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.
+ +
+ +```kotlin + +fun main() { +//sampleStart + fun getNullableLength(ns: String?) { + println("for \"$ns\":") + ns?.run { // 1 + println("\tis empty? " + isEmpty()) // 2 + println("\tlength = $length") + length // 3 + } + } + getNullableLength(null) + getNullableLength("") + getNullableLength("some string with Kotlin") +//sampleEnd +} +``` + +
+ + +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_stdlib/02_withFunction.md b/examples/06_scope_functions/03_with.md old mode 100755 new mode 100644 similarity index 70% rename from examples/06_stdlib/02_withFunction.md rename to examples/06_scope_functions/03_with.md index 6d5a3e9..d4e2b0c --- a/examples/06_stdlib/02_withFunction.md +++ b/examples/06_scope_functions/03_with.md @@ -1,6 +1,8 @@ + + # with -*with* function lets you access members of an object in a short and concise way. Inside the `with` block you can refer to object members without specifying its name as a prefix. +`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.
diff --git a/examples/06_scope_functions/04_apply.md b/examples/06_scope_functions/04_apply.md new file mode 100644 index 0000000..500346e --- /dev/null +++ b/examples/06_scope_functions/04_apply.md @@ -0,0 +1,32 @@ +# apply + +`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 +data class Person(var name: String, var age: Int, var about: String) { + constructor() : this("", 0, "") +} + +fun main() { +//sampleStart + val jake = Person() // 1 + val stringDescription = jake.apply { // 2 + name = "Jake" // 3 + age = 30 + about = "Android developer" + }.toString() // 4 +//sampleEnd + println(stringDescription) +} +``` + +
+ + +1. Creates a `Person()` instance with default property values. +2. Applies the code block (next 3 lines) to the instance. +3. Inside `apply`, it's equivalent to `jake.name = "Jake"`. +4. The return value is the instance itself, so you can chain other operations. diff --git a/examples/06_scope_functions/05_also.md b/examples/06_scope_functions/05_also.md new file mode 100644 index 0000000..f07367c --- /dev/null +++ b/examples/06_scope_functions/05_also.md @@ -0,0 +1,32 @@ +# also + +`also` works like [`apply`](04_apply.md): it executes a given block and returns the object called. +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 +data class Person(var name: String, var age: Int, var about: String) { + constructor() : this("", 0, "") +} + +fun writeCreationLog(p: Person) { + println("A new person ${p.name} was created.") +} + +fun main() { +//sampleStart + val jake = Person("Jake", 30, "Android developer") // 1 + .also { // 2 + writeCreationLog(it) // 3 + } +//sampleEnd +} +``` + +
+ +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/06_stdlib/00_description.md b/examples/06_stdlib/00_description.md deleted file mode 100755 index ae10ef8..0000000 --- a/examples/06_stdlib/00_description.md +++ /dev/null @@ -1,2 +0,0 @@ -# Standard Library - diff --git a/examples/06_stdlib/01_letFunction.md b/examples/06_stdlib/01_letFunction.md deleted file mode 100755 index 8ab3b09..0000000 --- a/examples/06_stdlib/01_letFunction.md +++ /dev/null @@ -1,66 +0,0 @@ -# let - -`let` function allows you to call a specified functional block on an object. This function is useful for scoping and null-checks. - -
- -```kotlin -fun main() { - - fun checkStringContent(ns: String?) { - println("for \"$ns\":") - - ns.let { // 1 - println("\tcontent: " + it) // 2 - } - } - - checkStringContent(null) - checkStringContent("") - checkStringContent("some string with Kotlin") - - fun checkNullableString(ns: String?) { - println("for \"$ns\":") - - ns?.let { // 3 - println("\tis empty? " + it.isEmpty()) - println("\tcontains Kotlin? " + it.contains("Kotlin")) - } - } - checkNullableString(null) - checkNullableString("") - checkNullableString("some string with Kotlin") -} - -``` - -
- -1. Defines a code block to execute on `ns`. -2. Inside the curly braces `ns` is accessible by the name `it`. -3. Uses a null-safe call, so `let` and its code block are executed only on non-null values. - -`let` can also be called on a result of another function execution: - -
- -```kotlin -fun getStringOfLength(l: Int) = ".".repeat(l) - -fun main() { - fun checkString(l: Int) { - val empty = getStringOfLength(l).let { - println("\"$it\" is empty: ${it.isEmpty()} ") // 1 - - } - } - - checkString(0) - checkString(1) -} - -``` - -
- -1. Here `it` is the result of the `getStringOfLength(l)` call. \ No newline at end of file