CLOVIS
10/19/2023, 1:32 PMval found = sequenceOf(1, 2, 3, 4, 5)
.filter { it % 2 == 0 }
.onEach { println("Remaining: $it") }
.any()
println(found)
I was expecting Remaining: 2
to appear, but no, the onEach
is never called. It seems that any
is able to know that there will be other elements without actually processing them. PlaygroundJoffrey
10/19/2023, 1:35 PMsequenceOf()
by a sequence { ... }
builder, it will print Remaining: 2
CLOVIS
10/19/2023, 1:36 PMany
. Replace any
by first
in my example, and you will see that the onEach
prints.Joffrey
10/19/2023, 1:36 PMany
CLOVIS
10/19/2023, 1:36 PMfilter
, my sequence is not fixed-length)first
by any
in your example, and you will see it doesn't print eitherJoffrey
10/19/2023, 1:37 PMfirst
and any
in your initial code, before trying the dynamic sequence, and I forgot to revert back to any
in my attempt 😅CLOVIS
10/19/2023, 1:38 PMany
is implemented with iterator().hasNext()
, and the iterator returned by onEach
just delegates its hasNext
to the previous layer, thus any
is able to ask the filter directly if there are any elements, without actually processing themJoffrey
10/19/2023, 1:38 PMCLOVIS
10/19/2023, 1:39 PMany
and first
to have the exact same side effectsJoffrey
10/19/2023, 1:40 PMany()
and first()
. any()
is more like asking a question about the state of the sequence, not really about processing items, which is the case for first()
.Youssef Shoaib [MOD]
10/19/2023, 1:53 PMfirst
needs to actually get an item out, while any
merely needs to know that one is available. Theoretically, you could have a (weird) onEach implementation that runs its block in hasNext()
and not next()
, but that'd be pointless in normal cases except in this exampleJoffrey
10/19/2023, 1:54 PMonEach
should only occur on items that are not filtered out, you can't run the onEach
code inside the filter lambda, it's not equivalentYoussef Shoaib [MOD]
10/19/2023, 1:55 PMany()
should only need to know if the filter succeeds, and it doesn't care that the mapping should actually take place and produce a result (although maybe there's an issue here with exceptions)fun main() {
val found = sequenceOf(1, 2, 3, 4, 5)
.filter { it % 2 == 0 }
.map { TODO() }
.onEach { println("Remaining: $it") }
.any()
println(found)
}
This prints true
, and I think I agree with that result, although I can see an argument that it should result in an exception instead.
I think due to the laziness of sequences it makes sense (in a Haskell-y way) that a sequence doesn't care about side effects until they absolutely have to run.Klitos Kyriacou
10/19/2023, 2:00 PMvar found = IntStream.of(1, 2, 3, 4, 5)
.filter(n -> n % 2 == 0)
.peek(n -> System.out.printf("Remaining: %s%n", n))
.anyMatch(x -> true);
This prints "Remaining: 2" because the element has to be examined and passed to the predicate of anyMatch
. Java doesn't have the equivalent of Kotlin's any()
.Youssef Shoaib [MOD]
10/19/2023, 2:02 PMSequence.any
documentation should have a note that any()
is not equivalent to any { true }
because of side effects and exceptionsJoffrey
10/19/2023, 2:04 PMany()
, Kotlin does have an equivalent to Java's anyMatch(e -> true)
(and that is any { true }
). So you're right I think it should be clarified in the docs that any()
is not the same as any { true }
regarding side effectsSam
10/19/2023, 2:34 PMJoffrey
10/19/2023, 2:35 PMCLOVIS
10/19/2023, 3:05 PM