Regenerated samples
This commit is contained in:
parent
f5ea6e73af
commit
a3d7a6660a
|
@ -1,25 +1,28 @@
|
|||
// Interoperability/BigFibonacci.kt
|
||||
package interop
|
||||
import atomictest.eq
|
||||
import bigint.*
|
||||
import java.math.BigInteger
|
||||
import java.math.BigInteger.ONE
|
||||
import java.math.BigInteger.ZERO
|
||||
|
||||
fun fibonacci(n: Int): BigInt {
|
||||
fun fibonacci(n: Int): BigInteger {
|
||||
tailrec fun fibonacci(
|
||||
n: Int,
|
||||
current: BigInt,
|
||||
next: BigInt
|
||||
): BigInt {
|
||||
current: BigInteger,
|
||||
next: BigInteger
|
||||
): BigInteger {
|
||||
if (n == 0) return current
|
||||
return fibonacci(
|
||||
n - 1, next, current + next)
|
||||
n - 1, next, current + next) // [1]
|
||||
}
|
||||
return fibonacci(n, zero, one)
|
||||
return fibonacci(n, ZERO, ONE)
|
||||
}
|
||||
|
||||
fun main() {
|
||||
(0..7).map { fibonacci(it) } eq
|
||||
"[0, 1, 1, 2, 3, 5, 8, 13]"
|
||||
fibonacci(22) eq 17711.big
|
||||
fibonacci(22) eq 17711.toBigInteger()
|
||||
fibonacci(150) eq
|
||||
"9969216677189303386214405760200".big
|
||||
"9969216677189303386214405760200"
|
||||
.toBigInteger()
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
// Interoperability/BigInt.kt
|
||||
package bigint
|
||||
package biginteger
|
||||
import java.math.BigInteger
|
||||
|
||||
typealias BigInt = BigInteger
|
||||
fun Int.toBigInteger(): BigInteger =
|
||||
BigInteger.valueOf(this.toLong())
|
||||
|
||||
val Int.big: BigInt
|
||||
get() = BigInt.valueOf(toLong())
|
||||
fun String.toBigInteger(): BigInteger =
|
||||
BigInteger(this)
|
||||
|
||||
val String.big: BigInt
|
||||
get() = BigInt(this)
|
||||
|
||||
val zero = BigInt.ZERO
|
||||
val one = BigInt.ONE
|
||||
operator fun BigInteger.plus(
|
||||
other: BigInteger
|
||||
): BigInteger = this.add(other)
|
|
@ -2,8 +2,8 @@
|
|||
package Interoperability;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class
|
||||
Chameleon implements Serializable {
|
||||
public class Chameleon
|
||||
implements Serializable {
|
||||
private int size;
|
||||
private String color;
|
||||
public int getSize() {
|
||||
|
|
|
@ -8,7 +8,7 @@ public class JavaChecked {
|
|||
// Build path to current source file, based
|
||||
// on directory where Gradle is invoked:
|
||||
static Path thisFile = Paths.get(
|
||||
"DataFiles", "file_real.txt");
|
||||
"DataFiles", "file_wubba.txt");
|
||||
public static void main(String[] args) {
|
||||
BufferedReader source = null;
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Interoperability/JavaWrapper.java
|
||||
package Interoperability;
|
||||
import java.util.List;
|
||||
|
||||
public class JavaWrapper {
|
||||
public static void main(String[] args) {
|
||||
// Primitive type
|
||||
int i = 10;
|
||||
// Wrapper types
|
||||
Integer iOrNull = null;
|
||||
List<Integer> list = List.of(1, 2, 3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Interoperability/UseDataClass.java
|
||||
package Interoperability;
|
||||
import java.util.HashMap;
|
||||
import static atomictest.AtomicTestKt.eq;
|
||||
|
||||
public class UseDataClass {
|
||||
public static void main(String[] args) {
|
||||
Muppet m = new Muppet("Ernie", 6);
|
||||
int ageErnie = m.getAge();
|
||||
m.setName("Bert");
|
||||
m.setAge(7);
|
||||
eq(ageErnie < m.getAge(), true);
|
||||
eq(m, "Muppet(name=Bert, age=7)");
|
||||
|
||||
// Call copy() from the data class:
|
||||
Muppet mc = m.copy("???", 5);
|
||||
eq(mc, "Muppet(name=???, age=5)");
|
||||
|
||||
HashMap<Muppet, String> hm =
|
||||
new HashMap<>();
|
||||
// Muppets work as hash keys:
|
||||
hm.put(m, "Happy Muppet");
|
||||
eq(hm.get(m), "Happy Muppet");
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Interoperability/UsingDataClass.java
|
||||
package Interoperability;
|
||||
import java.util.HashMap;
|
||||
import static atomictest.AtomicTestKt.eq;
|
||||
|
||||
public class UsingDataClass {
|
||||
public static void main(String[] args) {
|
||||
Data d = new Data("Alice", 22);
|
||||
String name = d.getName();
|
||||
d.setName("Bob");
|
||||
int age = d.getAge();
|
||||
d.setAge(age + 1);
|
||||
// toString():
|
||||
eq(d, "Data(name=Bob, age=23)");
|
||||
HashMap<Data, Integer> hm =
|
||||
new HashMap<>();
|
||||
hm.put(d, 47);
|
||||
// Data objects work as hash keys:
|
||||
eq((double)hm.get(d), (double)47);
|
||||
// Call copy() from the Data class:
|
||||
Data d2 = d.copy("Sam", 24);
|
||||
eq(d2, "Data(name=Sam, age=24)");
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ import atomictest.eq
|
|||
import java.io.File
|
||||
|
||||
fun main() {
|
||||
File("DataFiles/file_real.txt")
|
||||
File("DataFiles/file_wubba.txt")
|
||||
.readLines()[0] eq
|
||||
"wubba lubba dub dub"
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// Interoperability/KotlinDataClass.kt
|
||||
package Interoperability
|
||||
|
||||
data class Data(
|
||||
data class Muppet(
|
||||
var name: String,
|
||||
var age: Int
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
// Interoperability/KotlinWrapper.kt
|
||||
package interop
|
||||
|
||||
fun main() {
|
||||
// Generates a primitive int:
|
||||
val i = 10
|
||||
// Generates wrapper types:
|
||||
val iOrNull: Int? = null
|
||||
val list: List<Int> = listOf(1, 2, 3)
|
||||
}
|
|
@ -14,7 +14,7 @@ files:
|
|||
visible: true
|
||||
- name: src/KotlinDataClass.kt
|
||||
visible: true
|
||||
- name: src/Interoperability/UsingDataClass.java
|
||||
- name: src/Interoperability/UseDataClass.java
|
||||
visible: true
|
||||
- name: src/TopLevelFunction.kt
|
||||
visible: true
|
||||
|
@ -58,3 +58,7 @@ files:
|
|||
visible: true
|
||||
- name: src/ReadOnlyCollections.kt
|
||||
visible: true
|
||||
- name: src/Interoperability/JavaWrapper.java
|
||||
visible: true
|
||||
- name: src/KotlinWrapper.kt
|
||||
visible: true
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
wubba lubba dub dub
|
|
@ -1,9 +1,7 @@
|
|||
## Maps (#3)
|
||||
|
||||
If you commonly select elements from a `List` using keys, it makes sense to
|
||||
optimize by using a `Map` instead of a `List`. A `Map` finds an element in
|
||||
constant time. With a `List`, in the worst case you must iterate over every
|
||||
element.
|
||||
optimize by using a `Map` instead of a `List`.
|
||||
|
||||
Change the internal implementation of the `Cage` class to store elements in a
|
||||
`Map` rather than a `List`. To get an element use the `getValue()` member
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Summary 2 (#3)
|
||||
|
||||
Create a `FixedHolder` class with a constructor parameter that sets the
|
||||
Create a `FixedSizeHolder` class with a constructor parameter that sets the
|
||||
maximum number of `Any` objects that can be held. Add read-only `size` and
|
||||
`full` properties. If the user calls `add()` when it's `full`, throw an
|
||||
`IllegalStateException`.
|
||||
|
|
|
@ -11,9 +11,9 @@ example, `IV` contains two digits) and store the maximum value found so far. If
|
|||
the next Roman digit is greater than or equal to the current maximum value, add
|
||||
it to the result. If it's less than the maximum, subtract it instead. For
|
||||
example, to convert `XLIV = 44`, iterate over `VILX` which is the reverse of
|
||||
`XLIV`. You add `V`(`5`) and `L`(`50`), but subtract `1`(`I`) because it's less
|
||||
than the current maximum `V`, and subtract `10`(`X`) because it's less than the
|
||||
updated maximum `X`:
|
||||
`XLIV`. You add `5`(`V`) and subtract `1`(`I`) because it's less than the
|
||||
current maximum `5`(`V`), then and `50`(`L`) and subtract `10`(`X`) because it's
|
||||
less than the updated maximum `10`(`X`):
|
||||
|
||||
| numeral | current maximum | action |
|
||||
| ------- |-----------------|--------|
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
package extensionlambdas
|
||||
import atomictest.eq
|
||||
|
||||
val divideBy = fun Int.(d: Int): Boolean {
|
||||
return this % d == 0
|
||||
}
|
||||
|
||||
fun exec(
|
||||
arg1: Int, arg2: Int,
|
||||
f: Int.(Int) -> Boolean
|
||||
arg1: Int, arg2: Int,
|
||||
f: Int.(Int) -> Boolean
|
||||
) = arg1.f(arg2)
|
||||
|
||||
fun main() {
|
||||
10.divideBy(2) eq true
|
||||
10.divideBy(3) eq false
|
||||
exec(10, 2, divideBy) eq true
|
||||
exec(10, 3, divideBy) eq false
|
||||
exec(10, 2, fun Int.(d: Int): Boolean {
|
||||
return this % d == 0
|
||||
}) eq true
|
||||
}
|
|
@ -13,7 +13,7 @@ fun lambdaUnitReturn () {
|
|||
"So it can be anything ..."
|
||||
}
|
||||
unitReturn { 1 } // ... of any type ...
|
||||
unitReturn { } // ... or nothing
|
||||
unitReturn { } // ... or nothing
|
||||
nonUnitReturn {
|
||||
"Must return the proper type"
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@ private fun clean() = buildString {
|
|||
('a'..'z').forEach { append(it) }
|
||||
}
|
||||
|
||||
private fun cleaner() =
|
||||
"ABCs: " + ('a'..'z').fold("", String::plus)
|
||||
|
||||
fun main() {
|
||||
messy() eq clean()
|
||||
clean() eq cleaner()
|
||||
}
|
|
@ -2,6 +2,14 @@
|
|||
package extensionlambdas
|
||||
import atomictest.eq
|
||||
|
||||
fun String.transform1(
|
||||
n: Int, lambda: (String, Int) -> String
|
||||
) = lambda(this, n)
|
||||
|
||||
fun String.transform2(
|
||||
n: Int, lambda: String.(Int) -> String
|
||||
) = lambda(this, n)
|
||||
|
||||
val duplicate: String.(Int) -> String = {
|
||||
repeat(it)
|
||||
}
|
||||
|
@ -12,14 +20,6 @@ val alternate: String.(Int) -> String = {
|
|||
.joinToString("")
|
||||
}
|
||||
|
||||
fun String.transform1(
|
||||
n: Int, lambda: (String, Int) -> String
|
||||
) = lambda(this, n)
|
||||
|
||||
fun String.transform2(
|
||||
n: Int, lambda: String.(Int) -> String
|
||||
) = lambda(this, n)
|
||||
|
||||
fun main() {
|
||||
"hello".transform1(5, duplicate)
|
||||
.transform2(3, alternate) eq "hleolhleo"
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
// OperatorOverloading/AllOperators.kt
|
||||
package operatoroverloading
|
||||
|
||||
class C {
|
||||
// equals() cannot be an extension
|
||||
// function and must be defined specially:
|
||||
override operator
|
||||
fun equals(other: Any?) = true
|
||||
}
|
||||
|
||||
// Unary operators:
|
||||
operator fun C.unaryPlus() = this
|
||||
operator fun C.unaryMinus() = this
|
||||
operator fun C.not() = this
|
||||
|
||||
// Increment/decrement:
|
||||
operator fun C.inc() = this
|
||||
operator fun C.dec() = this
|
||||
|
||||
// Binary operators:
|
||||
operator fun C.plus(rv: C) = rv
|
||||
operator fun C.minus(rv: C) = rv
|
||||
operator fun C.times(rv: C) = rv
|
||||
operator fun C.div(rv: C) = rv
|
||||
operator fun C.rem(rv: C) = rv
|
||||
operator fun C.rangeTo(rv: C) = rv
|
||||
|
||||
// 'In' operator:
|
||||
operator fun C.contains(rv: C) = true
|
||||
|
||||
// Indexed access:
|
||||
operator fun C.get(i: Int) = this
|
||||
operator fun C.set(i: Int, c: C) = this
|
||||
|
||||
// Augmented assignment:
|
||||
operator fun C.plusAssign(rv: C) = Unit
|
||||
operator fun C.minusAssign(rv: C) = Unit
|
||||
operator fun C.timesAssign(rv: C) = Unit
|
||||
operator fun C.divAssign(rv: C) = Unit
|
||||
operator fun C.remAssign(rv: C) = Unit
|
||||
|
||||
// Comparison, must return Int:
|
||||
operator fun C.compareTo(rv: C) = 1
|
||||
|
||||
fun main() {
|
||||
val c = C()
|
||||
+c // unaryPlus()
|
||||
-c // unaryMinus()
|
||||
!c // not()
|
||||
var cc = C()
|
||||
cc++ // inc() (needs var)
|
||||
cc-- // dec() (needs var)
|
||||
c + c // plus()
|
||||
c - c // minus()
|
||||
c * c // times()
|
||||
c / c // div()
|
||||
c % c // rem()
|
||||
c..c // rangeTo()
|
||||
c in c // contains()
|
||||
c !in c // contains()
|
||||
c[2] // get()
|
||||
c[2] = c // set()
|
||||
c += c // plusAssign()
|
||||
c -= c // minusAssign()
|
||||
c *= c // timesAssign()
|
||||
c /= c // divAssign()
|
||||
c %= c // remAssign()
|
||||
// equals():
|
||||
c == c
|
||||
c != c
|
||||
// compareTo():
|
||||
c < c
|
||||
c > c
|
||||
c <= c
|
||||
c >= c
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// OperatorOverloading/ArithmeticOperators.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
// Unary operators:
|
||||
operator fun E.unaryPlus() = E(v)
|
||||
operator fun E.unaryMinus() = E(-v)
|
||||
operator fun E.not() = this
|
||||
|
||||
// Increment/decrement:
|
||||
operator fun E.inc() = E(v + 1)
|
||||
operator fun E.dec() = E(v - 1)
|
||||
|
||||
fun unary(a: E) {
|
||||
+a // unaryPlus()
|
||||
-a // unaryMinus()
|
||||
!a // not()
|
||||
|
||||
var b = a
|
||||
b++ // inc() (must be var)
|
||||
b-- // dec() (must be var)
|
||||
}
|
||||
|
||||
// Binary operators:
|
||||
operator fun E.plus(e: E) = E(v + e.v)
|
||||
operator fun E.minus(e: E) = E(v - e.v)
|
||||
operator fun E.times(e: E) = E(v * e.v)
|
||||
operator fun E.div(e: E) = E(v % e.v)
|
||||
operator fun E.rem(e: E) = E(v / e.v)
|
||||
|
||||
fun binary(a: E, b: E) {
|
||||
a + b // a.plus(b)
|
||||
a - b // a.minus(b)
|
||||
a * b // a.times(b)
|
||||
a / b // a.div(b)
|
||||
a % b // a.rem(b)
|
||||
}
|
||||
|
||||
// Augmented assignment:
|
||||
operator fun E.plusAssign(e: E) { v += e.v }
|
||||
operator fun E.minusAssign(e: E) { v - e.v }
|
||||
operator fun E.timesAssign(e: E) { v *= e.v }
|
||||
operator fun E.divAssign(e: E) { v /= e.v }
|
||||
operator fun E.remAssign(e: E) { v %= e.v }
|
||||
|
||||
fun assignment(a: E, b: E) {
|
||||
a += b // a.plusAssign(b)
|
||||
a -= b // a.minusAssign(b)
|
||||
a *= b // a.timesAssign(b)
|
||||
a /= b // a.divAssign(b)
|
||||
a %= b // a.remAssign(b)
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val a = E(2)
|
||||
val b = E(3)
|
||||
a + b eq E(5)
|
||||
a * b eq E(6)
|
||||
val x = E(1)
|
||||
x += b * b
|
||||
x eq E(10)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// OperatorOverloading/Comparison.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
operator fun E.compareTo(e: E): Int =
|
||||
v.compareTo(e.v)
|
||||
|
||||
fun main() {
|
||||
val a = E(2)
|
||||
val b = E(3)
|
||||
(a < b) eq true // a.compareTo(b) < 0
|
||||
(a > b) eq false // a.compareTo(b) > 0
|
||||
(a <= b) eq true // a.compareTo(b) <= 0
|
||||
(a >= b) eq false // a.compareTo(b) >= 0
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// OperatorOverloading/ConfusingPrecedence.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
fun main() {
|
||||
val x: Int? = 1
|
||||
val y: Int = 2
|
||||
val sum = x ?: 0 + y
|
||||
sum eq 1
|
||||
(x ?: 0) + y eq 3 // [1]
|
||||
x ?: (0 + y) eq 1 // [2]
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// OperatorOverloading/ContainerAccess.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
data class C(val c: MutableList<Int>) {
|
||||
override fun toString() = "C($c)"
|
||||
}
|
||||
|
||||
operator fun C.contains(e: E) = e.v in c
|
||||
|
||||
operator fun C.get(i: Int): E = E(c[i])
|
||||
|
||||
operator fun C.set(i: Int, e: E) {
|
||||
c[i] = e.v
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val c = C(mutableListOf(2, 3))
|
||||
(E(2) in c) eq true // c.contains(E(2))
|
||||
(E(4) in c) eq false // c.contains(E(4))
|
||||
c[1] eq E(3) // c.get(1)
|
||||
c[1] = E(4) // c.set(2, E(4))
|
||||
c eq C(mutableListOf(2, 4))
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// OperatorOverloading/DefaultEquality.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
class A(val i: Int)
|
||||
data class D(val i: Int)
|
||||
|
||||
fun main() {
|
||||
// Normal class:
|
||||
val a = A(1)
|
||||
val b = A(1)
|
||||
val c = a
|
||||
(a == b) eq false
|
||||
(a == c) eq true
|
||||
// Data class:
|
||||
val d = D(1)
|
||||
val e = D(1)
|
||||
(d == e) eq true
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// OperatorOverloading/DefiningEquality.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
class E(var v: Int) {
|
||||
override fun equals(other: Any?) = when {
|
||||
this === other -> true // [1]
|
||||
other !is E -> false // [2]
|
||||
else -> v == other.v // [3]
|
||||
}
|
||||
override fun hashCode(): Int = v
|
||||
override fun toString() = "E($v)"
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val a = E(1)
|
||||
val b = E(2)
|
||||
(a == b) eq false // a.equals(b)
|
||||
(a != b) eq true // !a.equals(b)
|
||||
// Reference equality:
|
||||
(E(1) === E(1)) eq false
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// OperatorOverloading/DifferentTypes.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
operator fun E.plus(i: Int) = E(v + i)
|
||||
|
||||
fun main() {
|
||||
E(1) + 10 eq E(11)
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// OperatorOverloading/EqualsForNullable.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
fun equalsWithIf(a: E?, b: E?) =
|
||||
if (a === null)
|
||||
b === null
|
||||
else
|
||||
a == b
|
||||
|
||||
fun equalsWithElvis(a: E?, b: E?) =
|
||||
a?.equals(b) ?: (b === null)
|
||||
|
||||
fun main() {
|
||||
val x: E? = null
|
||||
val y = E(0)
|
||||
val z: E? = null
|
||||
(x == y) eq false
|
||||
(x == z) eq true
|
||||
equalsWithIf(x, y) eq false
|
||||
equalsWithIf(x, z) eq true
|
||||
equalsWithElvis(x, y) eq false
|
||||
equalsWithElvis(x, z) eq true
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// OperatorOverloading/Ranges.kt
|
||||
package operatoroverloading
|
||||
import atomictest.eq
|
||||
|
||||
data class R(val r: IntRange) { // Range
|
||||
override fun toString() = "R($r)"
|
||||
}
|
||||
|
||||
operator fun E.rangeTo(e: E) = R(v..e.v)
|
||||
|
||||
operator fun R.contains(e: E): Boolean =
|
||||
e.v in r
|
||||
|
||||
fun main() {
|
||||
val a = E(2)
|
||||
val b = E(3)
|
||||
val r = a..b // a.rangeTo(b)
|
||||
(a in r) eq true // r.contains(a)
|
||||
(a !in r) eq false // !r.contains(a)
|
||||
r eq R(2..3)
|
||||
}
|
|
@ -6,8 +6,6 @@ files:
|
|||
visible: true
|
||||
- name: src/Molecule.kt
|
||||
visible: true
|
||||
- name: src/AllOperators.kt
|
||||
visible: true
|
||||
- name: src/Invoke.kt
|
||||
visible: true
|
||||
- name: src/StringInvoke.kt
|
||||
|
@ -16,3 +14,21 @@ files:
|
|||
visible: true
|
||||
- name: src/Swearing.kt
|
||||
visible: true
|
||||
- name: src/DifferentTypes.kt
|
||||
visible: true
|
||||
- name: src/Ranges.kt
|
||||
visible: true
|
||||
- name: src/ContainerAccess.kt
|
||||
visible: true
|
||||
- name: src/DefiningEquality.kt
|
||||
visible: true
|
||||
- name: src/ArithmeticOperators.kt
|
||||
visible: true
|
||||
- name: src/ConfusingPrecedence.kt
|
||||
visible: true
|
||||
- name: src/EqualsForNullable.kt
|
||||
visible: true
|
||||
- name: src/Comparison.kt
|
||||
visible: true
|
||||
- name: src/DefaultEquality.kt
|
||||
visible: true
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// PropertyDelegation/CarService.kt
|
||||
// DelegationTools/CarService.kt
|
||||
package propertydelegation
|
||||
import atomictest.eq
|
||||
|
||||
class Driver(
|
||||
val map: MutableMap<String, Any?>
|
||||
map: MutableMap<String, Any?>
|
||||
) {
|
||||
var name: String by map
|
||||
var age: Int by map
|
||||
|
@ -20,7 +20,7 @@ fun main() {
|
|||
"available" to false,
|
||||
"coord" to Pair(111.93, 1231.12)
|
||||
)
|
||||
val driver = Driver(info);
|
||||
val driver = Driver(info)
|
||||
driver.available eq false
|
||||
driver.available = true
|
||||
info eq "{name=Bruno Fiat, age=22, " +
|
|
@ -1,75 +0,0 @@
|
|||
// DelegationTools/DelegateProvider.kt
|
||||
package delegationtools
|
||||
import kotlin.reflect.KProperty
|
||||
import atomictest.*
|
||||
|
||||
class Delegate<T>(private var value: T) {
|
||||
operator fun getValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>
|
||||
): T {
|
||||
trace("getValue: $value")
|
||||
return value
|
||||
}
|
||||
operator fun setValue(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>,
|
||||
newValue: T
|
||||
) {
|
||||
trace("setValue: $newValue")
|
||||
value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
class DelegateProvider<T>(val value: T) {
|
||||
operator fun provideDelegate(
|
||||
thisRef: Any?,
|
||||
property: KProperty<*>
|
||||
): Delegate<T> {
|
||||
trace("providing Delegate($value)")
|
||||
return Delegate(value)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> delegate(value: T):
|
||||
DelegateProvider<T> {
|
||||
trace("creating DelegateProvider($value)")
|
||||
return DelegateProvider(value)
|
||||
}
|
||||
|
||||
fun main() {
|
||||
var x by delegate(3.14)
|
||||
trace("x created")
|
||||
var y by delegate("Hello")
|
||||
trace("y created")
|
||||
var z by DelegateProvider(true)
|
||||
trace("z created")
|
||||
x eq 3.14
|
||||
x = 1.62
|
||||
x eq 1.62
|
||||
y eq "Hello"
|
||||
y = "Goodbye"
|
||||
y eq "Goodbye"
|
||||
z eq true
|
||||
z = false
|
||||
z eq false
|
||||
trace eq """
|
||||
creating DelegateProvider(3.14)
|
||||
providing Delegate(3.14)
|
||||
x created
|
||||
creating DelegateProvider(Hello)
|
||||
providing Delegate(Hello)
|
||||
y created
|
||||
providing Delegate(true)
|
||||
z created
|
||||
getValue: 3.14
|
||||
setValue: 1.62
|
||||
getValue: 1.62
|
||||
getValue: Hello
|
||||
setValue: Goodbye
|
||||
getValue: Goodbye
|
||||
getValue: true
|
||||
setValue: false
|
||||
getValue: false
|
||||
"""
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// DelegationTools/MapAccessors.kt
|
||||
package delegationtools
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
operator fun MutableMap<String, Any>.getValue(
|
||||
thisRef: Any?, property: KProperty<*>
|
||||
): Any? {
|
||||
return this[property.name]
|
||||
}
|
||||
|
||||
operator fun MutableMap<String, Any>.setValue(
|
||||
thisRef: Any?, property: KProperty<*>,
|
||||
value: Any
|
||||
) {
|
||||
this[property.name] = value
|
||||
}
|
|
@ -6,5 +6,7 @@ files:
|
|||
visible: true
|
||||
- name: src/NeverNull.kt
|
||||
visible: true
|
||||
- name: src/DelegateProvider.kt
|
||||
- name: src/MapAccessors.kt
|
||||
visible: true
|
||||
- name: src/CarService.kt
|
||||
visible: true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PropertyDelegation/PropDelegationSoln1.kt
|
||||
package propertyDelegationExercise1
|
||||
package propertyDelegationToolsExercise1
|
||||
import atomictest.eq
|
||||
|
||||
class Configuration(
|
||||
|
|
|
@ -3,10 +3,10 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 103
|
||||
- offset: 108
|
||||
length: 141
|
||||
placeholder_text: class Configuration
|
||||
- offset: 259
|
||||
- offset: 264
|
||||
length: 323
|
||||
placeholder_text: |-
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation (#1)
|
||||
## Property Delegation Tools (#1)
|
||||
|
||||
Convert `Configuration.kt` to use a `Map` instead of a file. The starter code
|
||||
in `main()` tests your new `Configuration` class.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationExercise1
|
||||
package propertyDelegationToolsExercise1
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationExercise1 {
|
||||
class TestPropertyDelegationToolsExercise1 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// DelegationTools/DelegToolsSoln1.kt
|
||||
package propertyDelegationToolsExercise1
|
||||
package propertyDelegationToolsExercise2
|
||||
import kotlin.properties.Delegates
|
||||
import atomictest.*
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation Tools (#1)
|
||||
## Property Delegation Tools (#2)
|
||||
|
||||
The starter code defines a `data class` called `Flag` containing a `Boolean`
|
||||
called `b` with a default value of `false`. In `main()`, create three `var`s:
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationToolsExercise1
|
||||
package propertyDelegationToolsExercise2
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationToolsExercise1 {
|
||||
class TestPropertyDelegationToolsExercise2 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// DelegationTools/DelegToolsSoln2.kt
|
||||
package propertyDelegationToolsExercise2
|
||||
package propertyDelegationToolsExercise3
|
||||
import kotlin.properties.Delegates.observable
|
||||
import kotlin.reflect.KProperty
|
||||
import atomictest.*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation Tools (#2)
|
||||
## Property Delegation Tools (#3)
|
||||
|
||||
Create a generic function `observe()` that uses `trace()` to capture
|
||||
`"$propertyName $oldValue to $newValue"` whenever a property changes. Ensure
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationToolsExercise2
|
||||
package propertyDelegationToolsExercise3
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationToolsExercise2 {
|
||||
class TestPropertyDelegationToolsExercise3 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// DelegationTools/DelegToolsSoln3.kt
|
||||
package propertyDelegationToolsExercise3
|
||||
package propertyDelegationToolsExercise4
|
||||
import atomictest.eq
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation Tools (#3)
|
||||
## Property Delegation Tools (#4)
|
||||
|
||||
Create a `class PositiveInt(i: Int)` containing a property `var n` such that
|
||||
any value assigned to `n` can only be greater than zero. The starter code in
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationToolsExercise3
|
||||
package propertyDelegationToolsExercise4
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationToolsExercise3 {
|
||||
class TestPropertyDelegationToolsExercise4 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -18,5 +18,3 @@ files:
|
|||
visible: true
|
||||
- name: src/Configuration.kt
|
||||
visible: true
|
||||
- name: src/CarService.kt
|
||||
visible: true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PropertyDelegation/PropDelegationSoln2.kt
|
||||
package propertyDelegationExercise2
|
||||
package propertyDelegationExercise1
|
||||
import atomictest.eq
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation (#2)
|
||||
## Property Delegation (#1)
|
||||
|
||||
Starting with `Add.kt`, add a `setValue()` extension function to `Sum` that
|
||||
assigns its `value` argument to `a` in `Add` (change `Add` to make this work).
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationExercise2
|
||||
package propertyDelegationExercise1
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationExercise2 {
|
||||
class TestPropertyDelegationExercise1 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PropertyDelegation/PropDelegationSoln3.kt
|
||||
package propertyDelegationExercise3
|
||||
package propertyDelegationExercise2
|
||||
import atomictest.eq
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation (#3)
|
||||
## Property Delegation (#2)
|
||||
|
||||
Start with:
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationExercise3
|
||||
package propertyDelegationExercise2
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationExercise3 {
|
||||
class TestPropertyDelegationExercise2 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PropertyDelegation/PropDelegationSoln4.kt
|
||||
package propertyDelegationExercise4
|
||||
package propertyDelegationExercise3
|
||||
import atomictest.eq
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Property Delegation (#4)
|
||||
## Property Delegation (#3)
|
||||
|
||||
Create a generic class that begins:
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package propertyDelegationExercise4
|
||||
package propertyDelegationExercise3
|
||||
|
||||
import org.junit.Test
|
||||
import util.unimplementedTest
|
||||
|
||||
class TestPropertyDelegationExercise4 {
|
||||
class TestPropertyDelegationExercise3 {
|
||||
@Test fun testSolution() {
|
||||
unimplementedTest()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// ScopeFunctions/AndNullability.kt
|
||||
package scopefunctions
|
||||
import atomictest.eq
|
||||
import kotlin.random.Random
|
||||
|
||||
fun gets(): String? =
|
||||
if (Random.nextBoolean()) "str!" else null
|
||||
|
||||
fun main() {
|
||||
gets()?.let {
|
||||
it.removeSuffix("!") + it.length
|
||||
}?.eq("str4")
|
||||
}
|
|
@ -3,8 +3,9 @@ package scopefunctions
|
|||
import atomictest.*
|
||||
|
||||
data class Blob(val id: Int) : AutoCloseable {
|
||||
fun show() { trace("Show $id")}
|
||||
override fun close() = trace("Close $id")
|
||||
override fun toString() = "Blob($id)"
|
||||
fun show() { trace("$this")}
|
||||
override fun close() = trace("Close $this")
|
||||
}
|
||||
|
||||
fun main() {
|
||||
|
@ -19,20 +20,20 @@ fun main() {
|
|||
Blob(9).also { it.show() }.apply { close() }
|
||||
Blob(10).apply { show() }.use { }
|
||||
trace eq """
|
||||
Show 1
|
||||
Show 2
|
||||
Show 3
|
||||
Show 4
|
||||
Show 5
|
||||
Show 6
|
||||
Close 6
|
||||
Show 7
|
||||
Close 7
|
||||
Show 8
|
||||
Close 8
|
||||
Show 9
|
||||
Close 9
|
||||
Show 10
|
||||
Close 10
|
||||
Blob(1)
|
||||
Blob(2)
|
||||
Blob(3)
|
||||
Blob(4)
|
||||
Blob(5)
|
||||
Blob(6)
|
||||
Close Blob(6)
|
||||
Blob(7)
|
||||
Close Blob(7)
|
||||
Blob(8)
|
||||
Close Blob(8)
|
||||
Blob(9)
|
||||
Close Blob(9)
|
||||
Blob(10)
|
||||
Close Blob(10)
|
||||
"""
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
// ScopeFunctions/Differences.kt
|
||||
package scopefunctions
|
||||
import atomictest.eq
|
||||
|
||||
data class Tag(var n: Int = 0) {
|
||||
var s: String = ""
|
||||
fun increment() = ++n
|
||||
}
|
||||
|
||||
fun main() {
|
||||
// let(): Access object with 'it'
|
||||
// Returns last expression in lambda
|
||||
val let1: Int = Tag(1).let {
|
||||
it.s = "let: ${it.n}"
|
||||
it.increment()
|
||||
}
|
||||
let1 eq 2
|
||||
|
||||
// let() with named lambda argument:
|
||||
val let2: Int = Tag(2).let { tag ->
|
||||
tag.s = "let: ${tag.n}"
|
||||
tag.increment()
|
||||
}
|
||||
let2 eq 3
|
||||
|
||||
// run(): Access object with 'this'
|
||||
// Returns last expression in lambda
|
||||
val run1: Int = Tag(3).run {
|
||||
s = "run: $n"
|
||||
increment()
|
||||
}
|
||||
run1 eq 4
|
||||
|
||||
// with(): Access object with 'this'
|
||||
// Returns last expression in lambda
|
||||
val with1: Int = with(Tag(4)) {
|
||||
s = "with: $n"
|
||||
increment()
|
||||
}
|
||||
with1 eq 5
|
||||
|
||||
// apply(): Access object with 'this'
|
||||
// Returns modified object
|
||||
val apply1: Tag = Tag(5).apply {
|
||||
s = "apply: $n"
|
||||
increment()
|
||||
}
|
||||
apply1 eq "Tag(n=6)"
|
||||
|
||||
// also(): Access object with 'it'
|
||||
// Returns modified object
|
||||
val also1: Tag = Tag(6).also {
|
||||
it.s = "also: ${it.n}"
|
||||
it.increment()
|
||||
}
|
||||
also1 eq "Tag(n=7)"
|
||||
|
||||
// also() with named lambda argument:
|
||||
val also2: Tag = Tag(7).also { tag ->
|
||||
tag.s = "also: ${tag.n}"
|
||||
tag.increment()
|
||||
}
|
||||
also2 eq "Tag(n=8)"
|
||||
}
|
|
@ -9,7 +9,7 @@ fun display(map: Map<String, Plumbus>) {
|
|||
val pb1: Plumbus = map["main"]?.let {
|
||||
it.id += 10
|
||||
it
|
||||
} ?: return // [1]
|
||||
} ?: return
|
||||
trace(pb1)
|
||||
|
||||
val pb2: Plumbus? = map["main"]?.run {
|
||||
|
|
|
@ -6,23 +6,23 @@ val functions = listOf(
|
|||
fun(name: String?) {
|
||||
name
|
||||
?.takeUnless { it.isBlank() }
|
||||
?.let { trace("Hi! I am $it") }
|
||||
?.let { trace("$it in let") }
|
||||
},
|
||||
fun(name: String?) {
|
||||
name
|
||||
?.takeUnless { it.isBlank() }
|
||||
?.run { trace("Hi! I am $this") }
|
||||
?.run { trace("$this in run") }
|
||||
},
|
||||
fun(name: String?) {
|
||||
name
|
||||
?.takeUnless { it.isBlank() }
|
||||
?.apply { trace("Hi! I am $this") }
|
||||
?.apply { trace("$this in apply") }
|
||||
},
|
||||
fun(name: String?) {
|
||||
name
|
||||
?.takeUnless { it.isBlank() }
|
||||
?.also { trace("Hi! I am $it") }
|
||||
}
|
||||
?.also { trace("$it in also") }
|
||||
},
|
||||
)
|
||||
|
||||
fun main() {
|
||||
|
@ -30,9 +30,9 @@ fun main() {
|
|||
functions.forEach { it(" ") }
|
||||
functions.forEach { it("Yumyulack") }
|
||||
trace eq """
|
||||
Hi! I am Yumyulack
|
||||
Hi! I am Yumyulack
|
||||
Hi! I am Yumyulack
|
||||
Hi! I am Yumyulack
|
||||
Yumyulack in let
|
||||
Yumyulack in run
|
||||
Yumyulack in apply
|
||||
Yumyulack in also
|
||||
"""
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// ScopeFunctions/Nesting.kt
|
||||
package scopefunctions
|
||||
import atomictest.eq
|
||||
|
||||
fun nesting(s: String, i: Int): String =
|
||||
with(s) {
|
||||
with(i) {
|
||||
toString()
|
||||
}
|
||||
} +
|
||||
s.let {
|
||||
i.let {
|
||||
it.toString()
|
||||
}
|
||||
} +
|
||||
s.run {
|
||||
i.run {
|
||||
toString()
|
||||
}
|
||||
} +
|
||||
s.apply {
|
||||
i.apply {
|
||||
toString()
|
||||
}
|
||||
} +
|
||||
s.also {
|
||||
i.also {
|
||||
it.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
nesting("X", 7) eq "777XX"
|
||||
}
|