1
1
Fork 0

Added 'Lambda with Receiver' samples

This commit is contained in:
Svetlana Isakova 2020-04-15 21:23:48 +02:00
parent d1c7242fd1
commit ea45a18ae9
32 changed files with 230 additions and 123 deletions

View File

@ -0,0 +1,32 @@
// LocalFunctions/ReturningFunc.kt
package lambdawithreceiver
import atomictest.eq
fun first(): (Int) -> Int {
val func = fun (i: Int): Int {
return i + 1
}
func(1) eq 2
return func // [1]
}
fun second(): (String) -> String {
val func2 = { s: String -> "$s!" }
func2("abc") eq "abc!"
return func2 // [1]
}
fun third(): () -> String {
fun greet() = "Hi!"
return ::greet // [1]
}
fun main() {
val firstFun: (Int) -> Int = first()
val secondFun: (String) -> String = second()
val thirdFun: () -> String = third()
firstFun(42) eq 43 // [2]
secondFun("xyz") eq "xyz!" // [3]
thirdFun() eq "Hi!" // [4]
}

View File

@ -18,3 +18,5 @@ files:
visible: true
- name: src/ReturnInsideLambda.kt
visible: true
- name: src/ReturningFunc.kt
visible: true

View File

@ -4,7 +4,7 @@ The `createCounter()` function creates a pair of functions for managing the
counter. Instead of creating a class, we manipulate with a counter using only
functions.
In `createCounter` define a local variable `counter`. Then define two local
In `createCounter` define a local variable `counter`. Then define two local
functions:
- `inc()` - increases the `counter` value by one

View File

@ -1,6 +1,6 @@
## Local Functions (#3)
Complete the implementation of the `createContainer()` function. It returns
Complete the implementation of the `createContainer()` function. It returns
a pair of functions to control the integer container. The first function adds
an integer element to the container, the second function removes an element
from the container and returns it. If the container is empty, it returns `null`.

View File

@ -0,0 +1,11 @@
// LambdaWithReceiver/AnonymousFunction.kt
package lambdawithreceiver
import atomictest.eq
fun main() {
val divides = fun Int.(d: Int): Boolean {
return this % d == 0
}
10.divides(2) eq true
10.divides(3) eq false
}

View File

@ -1,4 +1,5 @@
// LambdaWithReceiver/BuildString.kt
package buildstring
import atomictest.eq
fun main() {

View File

@ -0,0 +1,10 @@
// LambdaWithReceiver/BuildStringDef.kt
package buildstring
fun buildString(
builderAction: StringBuilder.() -> Unit
): String {
val sb = StringBuilder()
sb.builderAction() // [1]
return sb.toString()
}

View File

@ -1,31 +0,0 @@
// LambdaWithReceiver/Declarations.kt
package lambdawithreceiver
import atomictest.eq
fun buildString1(
builderAction:
(StringBuilder) -> Unit // [1]
): String {
val sb = StringBuilder()
builderAction(sb) // [2]
return sb.toString()
}
fun buildString2(
builderAction:
StringBuilder.() -> Unit // [3]
): String {
val sb = StringBuilder()
sb.builderAction() // [4]
return sb.toString()
}
fun main() {
buildString1 {
it.append("Regular lambda")
} eq "Regular lambda"
buildString2 {
append("Lambda with receiver")
} eq "Lambda with receiver"
}

View File

@ -1,9 +1,7 @@
// LambdaWithReceiver/Extensions.kt
package lambdawithreceiver
package statemachine
fun StringBuilder.appendAlphabet() {
this.append("Alphabet:") // Explicit
for (ch in 'a'..'z') {
append(ch) // Implicit
}
fun StateMachine.pauseAndResume() {
this.pause() // Explicit
resume() // Implicit
}

View File

@ -1,24 +0,0 @@
// LambdaWithReceiver/NestedLWR.kt
package lambdawithreceiver
import atomictest.eq
fun Int.ext(): String.() -> Unit {
val func = lambda@ fun String.() {
val d = this // func's receiver
val d2 = this@lambda
d eq d2
}
val func2 = { s: String ->
// ext()'s receiver; enclosing
// lambda doesn't have a receiver
val d1 = this
}
"abc".func() // [1]
func2("abc")
return func // [2]
}
fun main() {
val funcHere = 1.ext()
"abc".funcHere() // [5]
}

View File

@ -0,0 +1,10 @@
// LambdaWithReceiver/NewStateMachine1.kt
package statemachine
fun newStateMachine1(
operate: (StateMachine) -> Unit
) {
val stateMachine = StateMachine()
stateMachine.start()
operate(stateMachine)
}

View File

@ -0,0 +1,28 @@
// LambdaWithReceiver/NewStateMachine2.kt
package statemachine2
import statemachine.StateMachine
fun newStateMachine1(
operate: (StateMachine) -> Unit // [1]
) {
val stateMachine = StateMachine()
stateMachine.start()
operate(stateMachine) // [2]
}
fun newStateMachine2(
operate: StateMachine.() -> Unit // [3]
) {
val stateMachine = StateMachine()
stateMachine.start()
stateMachine.operate() // [4]
}
fun main() {
newStateMachine1 {
it.finish()
}
newStateMachine2 {
finish()
}
}

View File

@ -1,21 +0,0 @@
// LambdaWithReceiver/RegularLambda.kt
package regularlambda
import atomictest.eq
fun buildStr(
builderAction: (StringBuilder) -> Unit
): String {
val sb = StringBuilder()
builderAction(sb)
return sb.toString()
}
fun main() {
buildStr {
it.append("Alphabet: ")
for (ch in 'a'..'z') {
it.append(ch)
}
} eq
"Alphabet: abcdefghijklmnopqrstuvwxyz"
}

View File

@ -0,0 +1,27 @@
// LambdaWithReceiver/StateMachine.kt
package statemachine
import statemachine.State.*
enum class State { ON, OFF, PAUSED }
class StateMachine {
var state: State = OFF
private set
private fun updateState(
current: State?, new: State
) {
if (current == null || state == current) {
println("$state -> $new")
state = new
}
}
fun start() = updateState(OFF, ON)
fun pause() = updateState(ON, PAUSED)
fun resume() = updateState(PAUSED, ON)
fun finish() = updateState(null, OFF)
}

View File

@ -0,0 +1,25 @@
// LambdaWithReceiver/UseNewStateMachine1.kt
package statemachine
fun main() {
println("first")
newStateMachine1 { sm -> // [1]
sm.finish() // [2]
}
println("second")
newStateMachine1 {
it.pause() // [3]
it.resume()
it.finish()
}
}
/* Output:
first
OFF -> ON
ON -> OFF
second
OFF -> ON
ON -> PAUSED
PAUSED -> ON
ON -> OFF
*/

View File

@ -0,0 +1,16 @@
// LambdaWithReceiver/UseNewStateMachine2.kt
package statemachine2
fun main() {
newStateMachine2 { // [1]
this.pause() // [2]
resume() // [3]
finish()
}
}
/* Output:
OFF -> ON
ON -> PAUSED
PAUSED -> ON
ON -> OFF
*/

View File

@ -1,14 +1,22 @@
type: theory
files:
- name: src/StringBuilder.kt
- name: src/StateMachine.kt
visible: true
- name: src/RegularLambda.kt
- name: src/UseNewStateMachine1.kt
visible: true
- name: src/BuildString.kt
- name: src/NewStateMachine1.kt
visible: true
- name: src/UseNewStateMachine2.kt
visible: true
- name: src/Extensions.kt
visible: true
- name: src/Declarations.kt
- name: src/NewStateMachine2.kt
visible: true
- name: src/NestedLWR.kt
- name: src/AnonymousFunction.kt
visible: true
- name: src/StringBuilder.kt
visible: true
- name: src/BuildString.kt
visible: true
- name: src/BuildStringDef.kt
visible: true

View File

@ -11,6 +11,6 @@ fun drawSquare(width: Int) = buildString {
fun main() {
drawSquare(3) eq
"""|***
|***
|***""".trimMargin()
|***
|***""".trimMargin()
}

View File

@ -1,7 +1,8 @@
## Lambda with Receiver (#1)
Implement `drawSquare()` to return a square of star symbols in a `String`. It
takes `width` as a parameter. For `width = 3` the following output is expected:
Implement `drawSquare()` to return a square of star symbols in a `String`
using `buildString`. `drawSquare()` takes `width` as a parameter. For
`width = 3` the following output is expected:
```text
***

View File

@ -1,4 +1,4 @@
## Lambda with Receiver (#2)
Implement `buildList()` which is similar to `buildString()`. `buildList()`
creates a mutable list and applies actions passed in a lambda parameter.
Implement `buildMap()` which is similar to `buildList()`. `buildMap()`
creates a mutable map and applies actions passed in a lambda parameter.

View File

@ -4,14 +4,14 @@ import atomictest.eq
fun Window.dup() =
Window("dup of $id").also {
it.x = this.x // [1]
it.x = this.x // [1]
it.y = this.y
it.w = this.w
it.h = this.h
}
fun Window.dup2() =
Window("dup of $id").also { win ->
Window("dup of $id").also { win -> // [2]
win.x = this.x
win.y = this.y
win.w = this.w

View File

@ -10,8 +10,8 @@ data class Window( // [1]
)
fun adjustWindowIfNotNull(window: Window?) {
window?.run { // [2]
this.x = 10 // [3]
window?.run { // [1]
this.x = 10 // [2]
y = 10
w *= 2
h *= 2
@ -23,4 +23,7 @@ fun main() {
val windowOrNull: Window? = null
adjustWindowIfNotNull(windowOrNull)
println("Nothing happens")
}
}
/* Output:
Nothing happens
*/

View File

@ -1,4 +1,4 @@
// MoreLibraryFunctions/ReadingName.kt
// ScopeFunctions/ReadingName.kt
fun main() {
println("Enter your name:")
readLine()

View File

@ -10,5 +10,5 @@ fun main() {
remove(0)
}
result eq listOf(17, 42)
mutableList eq listOf(17, 42)
result eq mutableList
}

View File

@ -1,4 +1,5 @@
## The `with()` Function (#1)
Implement `buildString()` using `with()` helper function.
Note that `with()` returns the result of the lambda.
Implement `buildString()` using `with()` function from the Kotlin standard
library. Note that `with()` defined in the library returns the result of the
lambda.

View File

@ -5,4 +5,4 @@ a lambda with receiver, implement the toy `with2()` function which
takes an ordinary lambda as a parameter instead of a lambda with receiver.
Note that there're no function analogous to `with2()` in the standard
library, however, there're similar extension functions taking ordinary
lambdas, as explained in [Library Helpers] atom.
lambdas, as explained in [Scope Functions] atom.

View File

@ -1,4 +1,4 @@
// CheckInstructions/LocalFile.kt
// CheckInstructions/DataFile.kt
package checkinstructions
import atomictest.eq
import java.io.File

View File

@ -2,7 +2,7 @@ type: theory
files:
- name: src/QuadraticRequire.kt
visible: true
- name: src/LocalFile.kt
- name: src/DataFile.kt
visible: true
- name: src/GetTrace.kt
visible: true

View File

@ -1,7 +1,7 @@
// UnitTesting/StateMachine.kt
package statemachine
package unittesting
import statemachine.State.*
import unittesting.State.*
enum class State { ON, OFF, PAUSED }

View File

@ -1,5 +1,5 @@
// UnitTesting/TestStateMachine.kt
package statemachine
package unittesting
import kotlin.test.*
class TestStateMachine {

View File

@ -3,7 +3,7 @@ package unittesting
import kotlin.test.*
fun testFoo2() = expect(42, "Wrong answer") {
foo()
foo()
}
fun main() {

View File

@ -1541,6 +1541,11 @@ public class TestAllExamples extends AbstractTestExamples {
testExample("../AtomicKotlinCourse/Functional Programming/Local Functions/Examples/src/InterestingSessions.kt", localfunctions.InterestingSessionsKt::main);
}
@Test
public void testReturningFunc() {
testExample("../AtomicKotlinCourse/Functional Programming/Local Functions/Examples/src/ReturningFunc.kt", lambdawithreceiver.ReturningFuncKt::main);
}
@Test
public void testReturnFromFun() {
testExample("../AtomicKotlinCourse/Functional Programming/Local Functions/Examples/src/ReturnFromFun.kt", ReturnFromFunKt::main);
@ -2046,6 +2051,11 @@ public class TestAllExamples extends AbstractTestExamples {
testExample("../AtomicKotlinCourse/Preventing Failure/Check Instructions/Examples/src/Postconditions.kt", checkinstructions.PostconditionsKt::main);
}
@Test
public void testDataFile() {
testExample("../AtomicKotlinCourse/Preventing Failure/Check Instructions/Examples/src/DataFile.kt", checkinstructions.DataFileKt::main);
}
@Test
public void testSingleArgRequire() {
testExample("../AtomicKotlinCourse/Preventing Failure/Check Instructions/Examples/src/SingleArgRequire.kt", checkinstructions.SingleArgRequireKt::main);
@ -2061,11 +2071,6 @@ public class TestAllExamples extends AbstractTestExamples {
testExample("../AtomicKotlinCourse/Preventing Failure/Check Instructions/Examples/src/QuadraticRequire.kt", checkinstructions.QuadraticRequireKt::main);
}
@Test
public void testLocalFile() {
testExample("../AtomicKotlinCourse/Preventing Failure/Check Instructions/Examples/src/LocalFile.kt", checkinstructions.LocalFileKt::main);
}
@Test
public void testFail() {
testExample("../AtomicKotlinCourse/Preventing Failure/The Nothing Type/Examples/src/Fail.kt", nothingtype.FailKt::main);
@ -2132,18 +2137,18 @@ public class TestAllExamples extends AbstractTestExamples {
}
@Test
public void testRegularLambda() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/RegularLambda.kt", regularlambda.RegularLambdaKt::main);
public void testNewStateMachine2() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/NewStateMachine2.kt", statemachine2.NewStateMachine2Kt::main);
}
@Test
public void testBuildString() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/BuildString.kt", BuildStringKt::main);
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/BuildString.kt", buildstring.BuildStringKt::main);
}
@Test
public void testDeclarations() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/Declarations.kt", lambdawithreceiver.DeclarationsKt::main);
public void testUseNewStateMachine2() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/UseNewStateMachine2.kt", statemachine2.UseNewStateMachine2Kt::main);
}
@Test
@ -2152,8 +2157,13 @@ public class TestAllExamples extends AbstractTestExamples {
}
@Test
public void testNestedLWR() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/NestedLWR.kt", lambdawithreceiver.NestedLWRKt::main);
public void testAnonymousFunction() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/AnonymousFunction.kt", lambdawithreceiver.AnonymousFunctionKt::main);
}
@Test
public void testUseNewStateMachine1() {
testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Examples/src/UseNewStateMachine1.kt", statemachine.UseNewStateMachine1Kt::main);
}
@Test