I have a `List<String>` and a function `f: S...
# announcements
e
I have a
List<String>
and a function
f: String -> T?
and would like to apply
f
to each element
s
of the list in order until
f(s)
is non-null, returning that
f(s)
. If
f(s)
is null for all values,
null
should be returned. Here’s an ugly implementation:
Copy code
fun g(list: List<String>): String? =
    if (list.isEmpty()) {
        null
    } else {
        f(list.first()) ?: g(list.subList(1, list.size))
    }
Can someone suggest a more elegant way? Here’s the code, if you’d like to play with it. https://pl.kotl.in/mByy6tkph
m
Yours is functional. This is what I would do
Copy code
list.firstOrNull{ f(it) != null }
Codefoematter doesnt seem to work on phone
e
Thanks, @Michael de Kaste!
Actually @Michael de Kaste, that isn’t working for me.
firstOrNull
expects a predicate. My function
f
is not a predicate.
This works but repeats a calculation:
Copy code
list.firstOrNull { f(it) != null }?.let { f(it) }
p
why not just
list.firstOrNull  { f(it) != null }
?
e
Thanks @parth but I need the return value from
f
.
p
ah, I understand now. honestly I think a for-loop might be the most readable option 😄
e
I was afraid of that. As you may have been able to tell from my original code, I think like a Scheme programmer.
👍 1
p
Copy code
for (s : list){
  val result = f(s)
  if (result == null) continue
  return result
}
🥇 1
I did SML way back in school, your code is familiar 😉
e
Thanks! Would this work?
Copy code
for( s : list){
  val result = f(s)
  if (result != null) {
    return result
  }
}
p
yeah totally; my last job was big on “early return” to avoid nesting logic, but your above code is synonymous
1
r
Copy code
for (s in list) return f(s) ?: continue
(Haven't tested it, and arguably far from readable)
👏🏾 1
🥇 1
👍 2
e
Ooh!
Very nice!
I had to add a
return null
after the for loop.
👍 1
a
Copy code
list.asSequence().map(f).firstOrNull { it != null }
I think this dtrt too. tmtowtdi 🙂
🥇 1
3
m
Copy code
list.mapNotNull(::f).firstOrNull()
(sorry I went to bed)
1
👍 1
r
@Michael de Kaste has a nice solution. This is equivalent to
Copy code
fun g(list: List<String>) = list.mapNotNull { str -> f(str) }.firstOrNull()
a
It will evaluate f against the whole list, though, rather than stopping after the first non-null
4
r
Good point.
m
Just add an asSequence before it?
e
I tried using @araqnid’s elegant version but couldn’t because
g
is a suspend function (something I didn’t mention). I ended up sticking with @Ruckus’s version. Thanks everyone! That was fun, and I learned from it.