-
Notifications
You must be signed in to change notification settings - Fork 448
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?
Changes from all commits
d3a72af
af88e21
795c444
53dc2e4
54d43fe
6c47bbe
e3640d9
c1cebf0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1272,36 +1272,75 @@ public fun <A> Iterable<A>.fold(MA: Monoid<A>): A = | |
public fun <A, B> Iterable<A>.foldMap(MB: Monoid<B>, f: (A) -> B): B = | ||
fold(MB.empty()) { acc, a -> MB.run { acc.combine(f(a)) } } | ||
|
||
/** | ||
* Applies function [f] to each element | ||
* and returns a list for the applied result Iterable<B>. | ||
* | ||
* ```kotlin | ||
* import arrow.core.crosswalk | ||
* import io.kotest.matchers.shouldBe | ||
* | ||
* fun test() { | ||
* val ints = listOf(1, 2) | ||
* val res = ints.crosswalk { i -> listOf("a${i}", "b${i}", "c${i}") } | ||
* res shouldBe listOf(listOf("a1", "a2"), listOf("b1", "b2"), listOf("c1", "c2")) | ||
* } | ||
* ``` | ||
*/ | ||
public fun <A, B> Iterable<A>.crosswalk(f: (A) -> Iterable<B>): List<List<B>> = | ||
fold(emptyList()) { bs, a -> | ||
f(a).align(bs) { ior -> | ||
ior.fold( | ||
{ listOf(it) }, | ||
::identity, | ||
{ l, r -> listOf(l) + r } | ||
{ l, r -> r + l } | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Applies function [f] to each element | ||
* and returns the concatenated Map of the applied result Map<K, V>. | ||
* | ||
* ```kotlin | ||
* import arrow.core.crosswalk | ||
* import io.kotest.matchers.shouldBe | ||
* | ||
* fun test() { | ||
* val ints = listOf(1, 2) | ||
* val res = ints.crosswalkMap { i -> mapOf("a" to i, "b" to i, "c" to i) } | ||
* res shouldBe listOf("a", "b", "c").map { a -> a to ints }.toMap() | ||
* } | ||
* ``` | ||
*/ | ||
public fun <A, K, V> Iterable<A>.crosswalkMap(f: (A) -> Map<K, V>): Map<K, List<V>> = | ||
fold(emptyMap()) { bs, a -> | ||
f(a).align(bs) { (_, ior) -> | ||
ior.fold( | ||
{ listOf(it) }, | ||
::identity, | ||
{ l, r -> listOf(l) + r } | ||
{ l, r -> r + l } | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Applies function [f] to each element | ||
* and returns the result Iterable<B> without null. | ||
* | ||
* ```kotlin | ||
* import arrow.core.crosswalk | ||
* import io.kotest.matchers.shouldBe | ||
* | ||
* fun test() { | ||
* val ints = listOf(1, 2) | ||
* val res = ints.crosswalkNull { i -> if (i % 2 == 0) "x${i}" else null } | ||
* 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 commentThe reason will be displayed to describe this comment to others. Learn more. If you pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly, this function should:
Does this make sense? Does this coincide with the behavior here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @serras Thank you for your reply.
I have the same understanding as you have written.
However, the behavior seems not to coincides with the understandings. 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")
}
}) |
||
fold<A, List<B>?>(emptyList()) { bs, a -> | ||
Ior.fromNullables(f(a), bs)?.fold( | ||
{ listOf(it) }, | ||
::identity, | ||
{ l, r -> listOf(l) + r } | ||
) | ||
} | ||
mapNotNull(f).takeIf { it.isNotEmpty() || !this.any() } | ||
|
||
@Deprecated("Not being used anymore. Will be removed from the binary in 2.0.0") | ||
@PublishedApi | ||
|
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
andcrosswalkNull
.