How would you structure and format this code? ``` ...
# getting-started
h
How would you structure and format this code?
Copy 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:
Copy code
(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
I think it’s confusing to use a pair as the accumulator, so instead I’d use
any {}
and two variables.
Copy code
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
👍 1
s
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).
👍 1
h
I can't use any because it's an iterator
I mean, I could do two passes, but it's gonna be slower
w
Also I'd recommend destructuring the Pair to explain what it represents:
Copy code
(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
Also the any return the first matching, could be really fast.
1
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
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
Have you try to use a sequence?
w
In this case fold is usually a good solution. One thing you could do to allow stopping iteration early is using
runningFold
and
takeWhile
Copy code
iterator.asSequence()
    .runningFold { acc, it -> /* operation here */ }
    .takeWhile { (left, right) -> !(left && right) } // Will stop as soon as both are true
    .last()
h
Good point, but it's easier to express in a for loop 🤷
w
Yes, luckily everyone is free to pick their style, but it's good that you considered sequences 🙂
h
Yes, sequences are good, but I have to ship fewer classes if I use a for loop
true story 1
w
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
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)