Is there a better way to write `listOfStuff.asSequ...
# getting-started
m
Is there a better way to write
listOfStuff.asSequence().mapNotNull { fromStuffToSomethingOrNull(it) }.firstOrNull()
a
Probably not, depending how its used the asSequence part may not be needed, usually for lazy evaluation of lists. Since its doing firstOrNull its using lazy evaluation to get only the first item which might defeat the purpose.
m
The
asSequence()
is there to avoid mapping all the items unnecessarily.
☝️ 2
m
I would at least factor it out to make the intend clear:
Copy code
inline fun <T, R : Any> List<T>.firstMappedNotNull(block: (T) -> R?): R? = asSequence().mapNotNull(block).firstOrNull()
Also I come up with an other implementation, but I definitely prefer yours, because it’s easier to read and understand.
Copy code
inline fun <T, R : Any> List<T>.firstMappedNotNull(block: (T) -> R?): R? = forEach { block(it)?.also { return it } }.let { null }
👍 1
m
And can apply to any iterable
Copy code
inline fun <T, R: Any> Iterable<T>.firstMappedOrNull(noinline block: (T) -> R?): R? = asSequence().mapNotNull(block).firstOrNull()
Bonus points for naming it
firstMapNotNullOrNull()
😉
😂 1
👍🏻 2
d
Copy code
for (i in list) return block(i) ?: continue
return null
👍 1
m
Nice!
m
It’s clever, but I don’t think as readable because
return block(i) ?: continue
is confusing. You have to work out that
block(i) ?: continue
will be evaluated first and so potentially avoid the return.
d
Then rewrite it to be clearer, it's peanuts
You can start by puttimg the expression after the return in parentheses, and you can then move the return into a .let {} on the following line, or expand the if block and make a variable.
block(i)?.let { return it }
perhaps
m
But now it’s less clear than
asSequence().mapNotNull(block).firstOrNull()
d
I don't think subjective discussions are helpful