Home > database >  What would be an idiomatic way in kotlin to generate a list of items by calling a function?
What would be an idiomatic way in kotlin to generate a list of items by calling a function?

Time:03-09

Let's say there is a function that returns a single nullable return value. For instance:

fun getItem(): String?

I'd like to create a new list of items by calling this function until it returns null.

My idea would be to write an iterator that iterates the return value until it's null. However, is there a more elegant or idiomatic way to approach this issue?

CodePudding user response:

Not sure about what would be idiomatic tbh, but you can use a simple while(true) to achieve it.

val list = mutableListOf<String>()

while (true) getItem()?.let { list  = it } ?: break

That basically translates to:

while true (infinite loop).
if getItem() is not null, add it to the list.
if getItem() is null, then break the loop. 

CodePudding user response:

Like @Slaw says in the comments, you can use generateSequence and pass it a reference to your function (or a lambda that calls it if you want) to create a Sequence that generates values. Terminating when your function returns null is built-in behaviour:

Returns a sequence which invokes the function to calculate the next value on each iteration until the function returns null.

So you can literally just do generateSequence(::getItem) to get your "iterator", and call toList or whatever sequences function you like on it. It's not an actual Iterator though - you can get one of those by doing toList() and then calling iterator() on that.

There's a bunch of ways to get this functionality, but generateSequence is the simplest I think. If you needed more control, you could chain a takeWhile() call to make a sequence that terminates on a specific condition/value, or you could use the sequence builder function to yield the items you need (say if you wanted to have nulls in there). And there's non-sequence approaches like @Alex.T's "add to a list" trick too (although - I haven't checked - I'd imagine that's what generateSequence -> toList is doing under the hood)

  • Related