How to explain implementation in Kotlin - kotlin

I am really new in Kotlin programming language. I work with generic types and I found code statements shown below. What does it means? What is the meaning of each line?
class s(val b: t) : t by b {
fun f1(): Int = b.f3 + 1
override fun f2(g: Int): Any? = when {
g == 0 -> null
else -> b.f2(g - 1)
}
override fun l(g: Int, h: k?, z: m):
k = when {
g == 0 -> z.f1.f2.f3(1, z, true)
else -> b.l(g - 1, h, z)}}
override fun f4 (g: Int): Short = when {
g == 0 -> 0
else -> b.f4(g - 1)}}}

Related

How can I check if a set of functions all return non null, in a single expression?

Suppose I have three functions foo, bar, baz, all of which return nullable types.
fun foo(): Int? = 1
fun bar(): Int? = 2
fun baz(): Int? = 3
I want to call them, and if all them returns non-null, I want to compute a value from their return values.
I could do this with statements, like this:
val x = foo()
val y = bar()
val z = baz()
val result = if (x != null && y != null && z != null) x + y + z else null
However, I don't like the fact that I have to declare 3 extra variables that I can still access afterwards. By having 3 extra statements like this, it also means that I cannot use expression-bodied functions, if I were writing a function that returns result.
If I use lets instead:
val result = foo()?.let { x ->
bar()?.let { y ->
baz()?.let { z ->
x + y + z
}
}
}
This creates a deep nesting. If it were only one function, this would have been fine, but with 3 functions or more, this makes my intention of "call these three functions, if they are all non null, add them together" rather unclear.
How can I write this in a way that clearly conveys my intention, but also making it a single expression?
If they are of different types, I think you need to write your own helper functions like these (different overloads needed for different numbers of parameters, because there's no other way for the compiler to know the types of the arguments):
inline fun <T : Any, U : Any, R> ifAllNotNull(t: T?, u: U?, block: (t: T, u: U) -> R): R? {
return when {
t != null && u != null -> block(t, u)
else -> null
}
}
inline fun <T : Any, U : Any, V : Any, R> ifAllNotNull(t: T?, u: U?, v: V?, block: (t: T, u: U, v: V) -> R): R? {
return when {
t != null && u != null && v != null -> block(t, u, v)
else -> null
}
}
val result = ifAllNotNull(foo(), bar(), baz()) { x, y, z -> x + y + z }
Note that all three parameters will be evaluated before any are checked for null.
Or if you want to do what you described (hiding the three variables after the result calculation) using just standard library functions, you can use run to limit the scope of the temporary variables:
val result = run {
val x = foo()
val y = bar()
val z = baz()
if (x != null && y != null && z != null) x + y + z else null
}
This would also give you the opportunity to short-circuit if you like:
val result = run {
val x = foo() ?: return#run null
val y = bar() ?: return#run null
val z = baz() ?: return#run null
x + y + z
}
You could filter out all null-values and only apply an operation on the list, if it did not shrink in size, e.g.:
fun sumIfNoneNull(values: List<Int?>): Int? = values
.filterNotNull()
.takeIf { it.size == values.size }
?.sum()
One may generalize this further, e.g.:
fun <T, R> List<T>.foldIfNoneNull(
initial: R,
operation: (acc: R, T) -> R
): R? = this
.filterNotNull()
.takeIf { nonNullList -> nonNullList.size == this.size }
?.fold(initial, operation)
You may use this like any other fold, e.g.:
listOf(foo(), bar(), baz()).foldIfNoneNull(0) { acc, cur -> acc + cur }
val result = listOf(foo(), bar(), baz())
.reduce { acc, i ->
when {
acc == null || i == null -> null
else -> acc + i
}
}
Or as function:
fun <T> apply(operation: (T, T) -> T, vararg values: T?): T? {
return values
.reduce { acc, i ->
when {
acc == null || i == null -> null
else -> operation(acc, i)
}
}
}
val result = apply({ x, y -> x + y }, foo(), bar(), baz())

Generic Kotlin factory to DRY constructor parameters

I have the following simple class hierarchy.
abstract class B {
abstract val o : Int
}
class D1 (m: Int, n: Int) : B() {
override val o = m + n
}
class D2 (m: Int, n: Int) : B() {
override val o = m * n
}
I need a "factory function" f that gives me instances of D1 or D2 by calling it as f<D1>() or f<D2>() with hard coded parameters, say 3 and 4. The following doesn't work but illustrates what I need:
// won't compile; just demonstrates what I need
fun < T : B > f () : T {
return T(3, 4) // i. e. return T.constructor(m, n)
}
How to best accomplish this? Any DRY way is fine as long I don't have to repeat 3, 4 all over my code when I instantiate D1 or D2
The only way to do it is via reflection and reified type parameter:
inline fun <reified T : B> f(m: Int = 3, n: Int = 4): T {
val constructor = T::class.constructors.first {
it.parameters.size == 2 &&
it.parameters.all { param -> param.type == Int::class }
}
return constructor.call(m, n)
}
Here's an alternate way without reflection, but you have to manually type out a line for each class you want to handle.
inline fun <reified T : B> f(): T{
val m = 3
val n = 4
return when (T::class) {
D1::class -> D1(m, n)
D2::class -> D2(m, n)
else -> error("Unsupported type ${T::class}")
} as T
}

Where is the memoization?

I am learning Kotlin and from the book, I have the fibonacci function, that demonstrates memoization concept:
import java.math.BigInteger
fun <T> List<T>.head(): T =
if (this.isEmpty())
throw IllegalArgumentException("head called on empty list")
else
this[0]
fun <T> List<T>.tail(): List<T> =
if (this.isEmpty())
throw IllegalArgumentException("tail called on empty list")
else
this.subList(1, this.size)
fun <T, U> foldLeft(list: List<T>, z: U, f: (U, T) -> U): U {
tailrec fun foldLeft(list: List<T>, acc: U, f: (U, T) -> U): U =
if (list.isEmpty())
acc
else
foldLeft(list.tail(), f(acc, list.head()), f)
return foldLeft(list, z, f)
}
fun fibo(number: Int): String {
tailrec fun fibo(
acc: List<BigInteger>, acc1: BigInteger,
acc2: BigInteger, x: BigInteger
): List<BigInteger> =
when (x) {
BigInteger.ZERO -> acc
BigInteger.ONE -> acc + (acc1 + acc2)
else -> fibo(
acc + (acc1 + acc2), acc2, acc1 + acc2,
x - BigInteger.ONE
)
}
val list = fibo(
listOf(),
BigInteger.ONE, BigInteger.ZERO, BigInteger.valueOf(number.toLong())
)
return makeString(list, ", ")
}
fun <T> makeString(list: List<T>, separator: String): String =
when {
list.isEmpty() -> ""
list.tail().isEmpty() -> list.head().toString()
else -> list.head().toString() +
foldLeft(list.tail(), "") { x, y -> x + separator + y }
}
fun main(args: Array<String>) {
println(fibo(5))
}
Could someone explain it to me, where is memoization here?
I... don't think there is any, actually.
What I wanted to write initially is that the acc parameter of the helper fibo function (the one with 4 parameters marked by tailrec) ends up containing the previous Fibonacci numbers, but it isn't actually accessed to retrieve them, so I don't think it counts.
Here is what I would consider memoization in this style (note: I made x an Int because it simplifies code and you won't calculate a Fibonacci number with index not fitting into a Long in sane time even with memoization):
fun fibo(x: Int): BigInteger {
tailrec fun fibo(
acc: List<BigInteger>, x: Int
): Pair<List<BigInteger>, BigInteger> =
when {
x < acc.size -> Pair(acc, acc[x])
x == acc.size -> {
val y = acc[x - 1] + acc[x - 2]
Pair(acc + y, y)
}
else ->
fibo(fibo(fibo(acc, x - 2).first, x - 1).first, x)
}
return fibo(listOf(BigInteger.ONE, BigInteger.ONE), x).second
}
You can simplify it a bit and make memoization (think a memo/note to remind you of something. Sort of like a cache.) a bit more explicit by doing something like this:
fun fib(n: Int, memo: MutableMap<Int, BigInteger> = mutableMapOf()): BigInteger {
if (memo.containsKey(n)) return memo[n]!!
if (n <= 2) return BigInteger.ONE
memo[n] = fib(n - 1, memo) + fib(n - 2, memo)
return memo[n]!!
}
You can see memoization in action here as each iteration stores the position and value of each number in the sequence. And within each fib call, we first check to see if the value already exists before creating another node in the call stack (think of each subsequent recursive call as creating a set of branching nodes until n is 1 or 2).
This is lightning fast, yielding linear O(n) time and space complexity even for cases like finding the 1000th number in the sequence. As opposed to O(2^n) without memoization.
First saw algorithm here and ported to kotlin: https://youtu.be/oBt53YbR9Kk

How to use Kotlin to Write a Y-combinator function?

Can I use Kotlin FP (Lambda, function) to write a Y-combinator function?
Y = λf.(λx.f (x x)) (λx.f (x x))
In JS:
function Y(f) {
return (function (g) {
return g(g);
})(function (g) {
return f(function (x) {
return g(g)(x);
});
});
}
var fact = Y(function (rec) {
return function (n) {
return n == 0 ? 1 : n * rec(n - 1);
};
});
In Coffee:
coffee> Y = (f) -> ((x) -> (x x)) ((x) -> (f ((y) -> ((x x) y))))
[Function]
coffee> fact = Y (f) ->(n) -> if n==0 then 1 else n*f(n-1)
[Function]
coffee> fact(10)
3628800
How can I do this?
In Kotlin, you should introduce an additional interface G, Otherwise you will get the UNCHECKED_CAST warnings, since Kotlin is a statically typed programming language rather than a dynamic language, for example:
typealias X = (Int) -> Int
typealias F = Function1<X, X>
// v-------------v--- let G reference G recursively
interface G : Function1<G, X>
// v--- create a G from lazy blocking
fun G(block: (G) -> X) = object : G {
// v--- delegate call `block(g)` like as `g(g)`
override fun invoke(g: G) = block(g)
}
fun Y(f: F) = (fun(g: G) = g(g))(G { g -> f({ x -> g(g)(x) }) })
val fact = Y({ rec -> { n -> if (n == 0) 1 else n * rec(n - 1) } })
Another version cast a Function1<G, X> to a G, so it should suppress the UNCHECKED_CAST warnings, for example:
typealias X = (Int) -> Int
typealias F = Function1<X, X>
typealias G = Function1<Any, X>
#Suppress("UNCHECKED_CAST")
// v--- cast `g` to `G`.
fun Y(f: F) = (fun(g: Function1<G, X>) = g(g as G))({ g -> f { x -> g(g)(x) } })
val fact = Y({ rec -> { n -> if (n == 0) 1 else n * rec(n - 1) } })

Elementary functions in kotlin

Looking for a way to get elementary functions and their derivatives I approach it like this:
abstract class Fun() {
/**
* i = 0 -- the function itself,
* i = 1, 2, 3, ... -- its successive derivatives
*/
abstract fun d(i: Int, x: Float): Float
}
class Lin(val k: Float) : Fun() {
// y = k*x
override fun d(i: Int, x: Float, p: Float) = when (i) {
0 -> k * x
1 -> k
else -> 0.0f
}
}
class Sum(val fun0: Fun, val fun1: Fun) : Fun() {
// y = fun0(x) + fun1(x)
override fun d(i: Int, x: Float, p: Float) = fun0.d(i, x) + fun1.d(i, x)
}
class Example(val fun1: Fun, val fun2: Fun){
var res = fun1.d(0, 5.25f) // fun1 value at 5.25f
res = fun1.d(1, 3.29f) // fun1 first derivative at 3.29f
val sum = Sum(fun1, fun2) // sum of f1 and f2
res = sum(0, 3.78f) // sum value at 3.78f
res = sum(1, 5.69f) // sum first derivative at 5.69f
}
Is there a more idiomatic way to do it in Kotlin?
I have exposed the problem as I had done in Java, that is, classes that contain functions. My question is if I can do the same with functions, pass them on to a class like:
class ParametricCurveXYZ(val fun_x: Fun, val fun_y: Fun, val fun_z: Fun) {
fun pointToXYZ(s: Float) = VectorXYZ(fun_x.d(0, s), fun_y.d(0, s), fun_z.d(0, s))
fun tangent(s: Float) = VectorXYZ(fun_x.d(1, s), fun_y.d(1, s), fun_z.d(1, s)).normalized()
}
You can use lambdas instead of regular classes and overload operators to combine lambdas.
fun lin(k: Float) = { i: Int, x: Float ->
when (i) {
0 -> k * x
1 -> k
else -> 0.0f
}
}
operator fun ((Int, Float) -> Float).plus(that: (Int, Float) -> Float) =
{ i: Int, x: Float -> this(i, x) + that(i, x) }
fun doSomething() {
val sum = lin(1f) + lin(2f)
val res = sum(0, 3.78f)
}