https://kotlinlang.org logo
Title
h

Hackintoshfive

04/13/2023, 4:17 PM
How would you structure and format this code?
val (rootMountedOrSystemRoot, hasSystemPartition) = lines.fold(false to false) { acc, it ->
                        (
                                acc.first
                                        || it.device == "/dev/root" && it.mountpoint == "/"
                                        || it.mountpoint == "/system_root" && it.type != "tmpfs"
                        ) to (
                                acc.second
                                        || it.mountpoint == "/system" && it.type != "tmpfs" && it.device != "none"
                        )
                    }
There's a more generic version in the comments
I'll get rid of the scary conditions to make it more readable
Here's a more generic example:
(0 until 10).fold(false to false) { acc, it ->
    (
            acc.first
                    || it.mod(2) == 0
    ) to (
            acc.second
                    || it.mod(3) == 0
                    || it.mod(5) == 1
    )
}
a

Adam S

04/13/2023, 5:03 PM
I think it’s confusing to use a pair as the accumulator, so instead I’d use
any {}
and two variables.
val values = (0 until 10)

val hasEvenNumbers = values.any { it % 2 == 0 }
val hasFooNumbers = values.any { it % 3 == 0 || it % 5 == 1 }

return hasEvenNumbers to hasFooNumbers
s

sciack

04/13/2023, 5:06 PM
In addition I will create function in
it
type (or extension function) that return true/false based on the 3 original condition, this make everything more readable (if the function has a good name).
h

Hackintoshfive

04/13/2023, 5:36 PM
I can't use any because it's an iterator
I mean, I could do two passes, but it's gonna be slower
w

Wout Werkman

04/13/2023, 6:12 PM
Also I'd recommend destructuring the Pair to explain what it represents:
(0 until 10).fold(false to false) { (evenNumbersFound, fooNumbersFound), it ->
Doing 2 passes using any* on an IntRange will very likely be faster than the fold, which will instantiate a Pair on each iteration
s

sciack

04/13/2023, 6:15 PM
Also the any return the first matching, could be really fast.
And how many object do you have? and in reality complexity is almost the same, is both linear and both condition evaluated. Unless iterating the list is really slow due to some network/os slow call.
h

Hackintoshfive

04/14/2023, 9:19 AM
It's not an IntRange, it's an Iterator. Either I call .toList() before I use .any{}, or I call .fold{}. Iterator reads from the disk and could potentially take a lot of RAM to convert to List.
I think that a for-loop is cleanest, to be honest.
s

sciack

04/14/2023, 9:24 AM
Have you try to use a sequence?
w

Wout Werkman

04/14/2023, 9:24 AM
In this case fold is usually a good solution. One thing you could do to allow stopping iteration early is using
runningFold
and
takeWhile
iterator.asSequence()
    .runningFold { acc, it -> /* operation here */ }
    .takeWhile { (left, right) -> !(left && right) } // Will stop as soon as both are true
    .last()
h

Hackintoshfive

04/14/2023, 9:30 AM
Good point, but it's easier to express in a for loop 🤷
w

Wout Werkman

04/14/2023, 9:32 AM
Yes, luckily everyone is free to pick their style, but it's good that you considered sequences 🙂
h

Hackintoshfive

04/14/2023, 9:35 AM
Yes, sequences are good, but I have to ship fewer classes if I use a for loop
w

Wout Werkman

04/14/2023, 9:38 AM
Not trying to convince anyone, but I feel this has to be mentioned. One additional advantage of using functional map-reduce or friends is that they are generally quite easy to parallelize.
h

Hackintoshfive

04/14/2023, 10:01 AM
Well since all I'm doing is binary ORs, I don't think parallelization is a big concern. But I am interested, how would I do this? Obviously the best approach is to split the list into N chunks, OR the elements of each chunk, then OR the chunks, but how would I do this? (I'm also sending to the channel because we've changed topic so much and people might be interested in the new one)