-
Notifications
You must be signed in to change notification settings - Fork 449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add some Iterable tests (#2894) #3040
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thank you @jsoizo 🙌
I will add a few more except for the ones with @deprecated annotations.
Do you want to add them in this PR, or another one? Whatever works best for you is fine
import io.kotest.property.arbitrary.boolean | ||
import io.kotest.property.arbitrary.int | ||
import io.kotest.property.arbitrary.list | ||
import io.kotest.property.arbitrary.orNull | ||
import io.kotest.property.arbitrary.pair | ||
import io.kotest.property.arbitrary.string | ||
import io.kotest.property.arbitrary.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use *
imports in the Arrow codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use * imports in the Arrow codebase.
I've put that back in.
Do you want to add them in this PR, or another one?
I will create another one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nomisRev I have added some tests and kDocs, could you please review them again?
Also, I have a question about the crosswalk implementation and left a comment with a question.
* Applies function [f] to each element | ||
* and returns a list for the applied result Iterable<B>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this explanation is adequate and would be happy to receive a revised proposal.
The same goes for crosswalkMap
and crosswalkNull
.
* res shouldBe listOf("x2") | ||
* } | ||
* ``` | ||
*/ | ||
public fun <A, B> Iterable<A>.crosswalkNull(f: (A) -> B?): List<B>? = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you pass emptyList()
as the first argument of fold, the results of Ior.fromNullables
and croswalkNull
will also not be null, since bs
is always non-null. If you expect croswalkNull
to be null if Iterable<A>
is empty or all results of applying the function f
are null, it is better to pass null as the first argument of fold.
Furthermore, it appears that if we modify it as described, crosswalkNull
will no longer return an empty list, so it would be a good idea to set the return type to NonEmptyList<B>?
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, this function should:
- return
null
if (and only if)f(it)
returnsnull
for some component, - return
emptyList()
if theIterable
is empty - return non-empty for a non-empty list where evey application of
f
returns non-null
.
Does this make sense? Does this coincide with the behavior here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@serras Thank you for your reply.
Does this make sense?
I have the same understanding as you have written.
Does this coincide with the behavior here?
However, the behavior seems not to coincides with the understandings.
The first and third case of following tests fails.
class CrosswalkNullTest : FunSpec({
test("return null if f(it) returns null") {
val list = listOf(1, 2, 3)
val result = list.crosswalkNull { null }
// This test fails because result is emptyList()
result shouldBe null
}
test("return emptyList() if Iterable is empty") {
val list = emptyList<Int>()
val result = list.crosswalkNull { it.toString() }
// This test passes
result shouldBe emptyList()
}
test("return non-empty if Iterable is non-empty and f(it) returns not-null") {
val list = listOf(1, 2, 3)
val result = list.crosswalkNull { it.toString() }
// This test fails because result is listOf("3", "2", "1")
result shouldBe listOf("1", "2", "3")
}
})
* fun test() { | ||
* val ints = listOf(1, 2) | ||
* val res = ints.crosswalk { i -> listOf("a${i}", "b${i}", "c${i}") } | ||
* res shouldBe listOf(listOf("a2", "a1"), listOf("b2", "b1"), listOf("c2", "c1")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The third argument to ior.fold
, listOf(l) + r
, makes the list appear to be in reverse order of the original list. I would think that r +l
would be a better behavior, but what do you think?
f(a).align(bs) { ior ->
ior.fold(
{ listOf(it) },
::identity,
{ l, r -> listOf(l) + r }
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, this seems wrong to me too. WDYT, @nomisRev?
This is an additional test to increase coverage of Iterable #2894 .
I will add a few more except for the ones with
@deprecated
annotations.