i'm playing around with map in kotlin, and currently I would like to see whether it would be possible to map a list of integers to a list of functions (Int) -> Int, while doing a bunch of operations inside the lambda that would require me to save values to vals
So I have this simple code:
val num = arrayOf(1, 2, 3, 4)
val funcs = num.map <Int, (Int) -> Int > { x -> {
y -> y + x
}}
This is a bit of a condensed example, the thing i'm really trying to do is a bit more convoluted. But I need to quite a bit of operations inside of of the 'inner' lambda, so I need to write codeblocks where I can use val. Like this:
val fs = num.map <Int, (Int) -> Int > { x -> {
y -> {
val tmp = y *2
val tmp1 = x / 2
tmp + tmp1
}
}}
But this part doesnt work, the compiler is confused by return types
How can I do something like this?
The reason your code in particular does not work is because you are adding an extra { after y -> in the second example:
val fs = num.map<Int, (Int) -> Int> { x ->
{ y ->
{ // this is not needed
val tmp = y * 2
val tmp1 = x / 2
tmp + tmp1
}// this is not needed
}
}
So you are creating a "block" of {} which in kotlin means that you are creating a lambda function. The reason block is in quotes is because if you truly want a block in kotlin the syntax is run {}, as opposed to the java {}. But again, you do not need it here.
All you have to do is remove the extra brackets and your code is fine:
val fs = num.map <Int, (Int) -> Int > { x -> {
y ->
val tmp = y *2
val tmp1 = x / 2
tmp + tmp1
}}
There is no difference between single-line and multi-line lambda
val fs = num.map { x ->
{ y: Int ->
val tmp = y * 2
val tmp1 = x / 2
tmp + tmp1
}
}
Related
See the following code where I tried out how already been declared variable x acts after being newly bound and then used within a function declaration. Why it is acting like this?
- val x = 2;
val x = 2 : int
- fun addx y = y + x;
val addx = fn : int -> int
- addx(5);
val it = 7 : int
- val x = 5;
val x = 5 : int
- addx(5);
val it = 7 : int
- subx y = y - x;
- fun subx y = y - x;
val subx = fn : int -> int
- subx(7);
val it = 2 : int
- 3 + x;
val it = 8 : int
- addx(10);
val it = 12 : int
This is caused by a combination of two features: immutability and variable shadowing. Variables are immutable, and cannot be reassigned to new values. But SML does allow you to shadow variable bindings, meaning that you are allowed to reuse an existing variable name for a new purpose (within a new lexical scope).
In the code you wrote, you used the name x twice for two different variables. The second declaration of x shadows the first, i.e., any code in the lexical scope that follows which mentions x is referring to the new declaration, not the old one. (Because of this possible confusion, some people consider variable shadowing to be bad code style.)
We can rename the second declaration to make everything much clearer:
- val x = 2;
val x = 2 : int
- fun addx y = y + x;
val addx = fn : int -> int
- addx(5);
val it = 7 : int
- val DIFFERENT_VARIABLE = 5;
val DIFFERENT_VARIABLE = 5 : int
- addx(5);
val it = 7 : int
- fun subx y = y - DIFFERENT_VARIABLE;
val subx = fn : int -> int
- subx(7);
val it = 2 : int
- 3 + DIFFERENT_VARIABLE;
val it = 8 : int
- addx(10);
val it = 12 : int
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())
I have a set of Cells
data class Cell(val i: Int, val j: Int)
that I initialize in my class like this
protected val board = mutableSetOf<Cell>()
init {
for (i in 1..width) {
for (j in 1..width) {
board += Cell(i, j)
}
}
}
Is there a more idiomatic (functional) way to initialize the set?
Ideally I would like the set to be immutable, because after this initialization it should never be changed.
You could define an extension that takes in a transformer to get the combinations as a pair of integers, then map it to a Cell. For instance:
inline fun <R> IntRange.combine(block: (Int, Int) -> R): Set<R> {
return flatMap { x -> map { y -> block(x, y) } }.toSet()
}
And then you can initialize with:
protected val board = (1..width).combine { x, y -> Cell(x, y) }
or simply:
protected val board = (1..width).flatMap { i -> (1..width).map { j -> Cell(i, j) } }
I think the former is more readable, though.
Unfortunately there is no constructor or top-level function to make the creation of a set following a certain logic easy, but if you already have a list you can turn it into a Set using toSet().
In any case I would separate the logic of creating a list of combinations and the creation of the Cell instances.
// extension property on IntRange to create all possible combinations
val IntRange.combinations get() = flatMap { i -> map { j -> i to j }}
val set = (1..5)
.combinations
.map { (i, j) -> Cell(i, j) }
.toSet()
Addition:
If you create a secondary constructor for Cell which takes a Pair like this:
data class Cell(val i: Int, val j: Int) {
constructor(pair: Pair<Int, Int>): this(pair.first, pair.second)
}
you can shorten the code to this:
val set = (1..5).combinations.map(::Cell).toSet()
You can do this
fun initBoard(width: Int): Set<Cell> {
return List<Cell>(width * width) { index ->
val i = index / width
val j = index % width
Cell(i + 1, j + 1)
}.toSet()
}
then in your init block
lateinit var board: Set<Cell>
init {
board = initBoard(width)
}
I don't see any examples of how to use tuples in Kotlin.
The errors i get on the first line (method definition) is "unresolved reference: a" and "expecting member declaration" for Int...
private fun playingAround : Pair<out a: Int, out b: Int> {
if(b != 0) {
b = a
a = a * 2
} else {
b = a
a = a * 3
}
return Pair(a, b)
}
About the logic: b is 0 in the beginning and a has a random value.
From the second call on, we go into the else logic.
i don't feel the official doc is enough: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html. I did try also without the ":" after the method name like the official doc seems to imply
-same problem
You are using incorrect syntax. It should be something like this:
private fun playingAround(a: Int, b: Int): Pair<Int, Int> {
val x: Int
val y: Int
if (b != 0) {
y = a
x = a * 2
} else {
y = a
x = a * 3
}
return Pair(x, y)
}
Note that a and b are method parameter values which cannot be reassigned, so you need variables x and y to store the result.
You can write this with much shorter syntax though:
private fun playingAround(a: Int, b: Int) = if (b != 0) Pair(a * 2, a) else Pair(a * 3, a)
Please have a look at the functions chapter of the kotlin reference and/or play around with the Kotlin koans to get familiar with Kotlin (or if, by any means, reading grammar is your favorite, have a look at the function declaration grammar instead; if you do not get what's written there, no problem. Start with the tutorials/reference instead).
One of the solutions could look like this:
private fun playingAround(a: Int, b: Int) = b.let {
if (it != 0) a * 2
else a * 3
} to a
or if you meant, that you actually want to pass a pair, then maybe the following is better:
private fun playingAround(givenPair: Pair<Int, Int>) = givenPair.let { (a, b) ->
b.let {
if (it != 0) a * 2
else a * 3
} to a
}
It's hard to really know what you wanted to accomplish as you didn't really specify what that is.
Extension function instead? For completeness:
private fun Pair<Int, Int>.playingAround() = let { (a, b) ->
b.let {
if (it != 0) a * 2
else a * 3
} to a
}
and of course: you do not need to use let, nor to use to, nor to use destructuring declarations, etc. There are just some of many possible solutions.
You can rewrite your code as the following:
private fun playingAround(a: Int, b: Int) : Pair<Int, Int> {
val tempA: Int
val tempB: Int
if(b != 0) {
tempB = a
tempA = a * 2
} else {
tempB = a
tempA = a * 3
}
return Pair(tempA, tempB)
}
And using Destructuring Declarations you can write the following:
val (a, b) = playingAround(1, 2)
Your function syntax is not correct. I suggest to study the documentation first.
To make this a bit more Kotlin-idiomatic, use if as an expression:
private fun playingAround(a: Int, b: Int): Pair<Int, Int> =
if (b != 0) {
Pair(a * 2, a)
} else {
Pair(a * 3, a)
}
I want to create a string which would contain a * symbol n times.
I only see this way:
val s = ""
val n = 100
for (j in 0 until n) {
s += "*"
}
But it looks ugly and it has a O(n^2) time complexity. Is there a way in Kotlin to do that without a loop with better time complexity?
The built in CharSequence.repeat extension does this in an efficient way, see the source here.
val str: String = "*".repeat(100)
Of course, this will still require O(n) steps to create the string. However, using this built-in stdlib function has its advantages: it's cross-platform, easy to read, and can be improved in performance over time, if there's a more efficient solution. The loop inside it will probably be optimized by the compiler or the runtime anyway.
You can overload the * operator to map it to the existing repeat extension:
public operator fun CharSequence.times(count: Int): String {
return repeat(count)
}
fun main() {
val s = "*" * 101
println(s)
println("Badger " * 12 + "Mushroom " * 2)
println(s)
}
An alternative to the CharSequence.repeat is a CharArray with an init function:
CharArray(N, {i -> '*'}).joinToString(separator="")
This solution has the advantage that you can define prefix, postfix, and separator.
StringBuilder would improve the memory footprint here:
val sb = StringBuilder()
val n = 100
for (j in 0 until n) {
sb.append("*")
}
If you need a separator, this initializer function from List is helpful:
val str: String = List(100) { "*" }.joinToString(",")
Thanks to Anton Sizikov and https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html, we can write:
val sb = StringBuilder().apply{
repeat(100) {
append("*")
}
}
But this is a simple way. Look at a power function. It has O(log n) complexity.
For StringBuilder:
private fun power(sb: StringBuilder, n: Int): StringBuilder =
when {
n == 0 -> StringBuilder("")
n % 2 == 0 -> {
val part = power(sb, n / 2)
part.append(part)
}
else -> {
val part = power(sb, n / 2)
part.append(part).append(sb)
}
}
For String:
private fun pow(s: String, n: Int): String =
when {
n == 0 -> ""
n % 2 == 0 -> pow(s, n / 2).repeat(2)
else -> s + pow(s, n / 2).repeat(2)
}
Then we can invoke them:
// 1.
val sb1 = StringBuilder().apply {
repeat(100) {
append("*")
}
}
// 2.
val sb2 = power(StringBuilder("*"), 100)
// 3.
val s = power("*", 100)
println(sb1.toString())
println(s)
println(sb2.toString())