1.6 way to use Flows to an updating state (scan? StateFlow?)

I’m behind the times (circa Kotlin 1.3), and would like to use the latest flow functions to do this the most “clean” way.

  1. I have a flow of messages
  2. Those messages update a state of the current “span”
  3. Sometimes those messages indicate the end of the current span, time to emit a completed “unit” of work.

Is this a MutableStateFlow?

I made up a toy case of listening to the radio to demonstrate the question:

commandLineToFlow(command = "listen to the radio") // works!
.dropExtraNoise() // Commercials, so many commercials.
.logToKnownUpdates() // classify and formalize! 
.distinctUntilChanged() // avoid repeats
.onEach { println("-- A message we should act on: $it") }
.transform<Message, Song> { message->
    // New song started, emit old song
    // this part feels... kludgy.  
    if((message.type ==Type.TITLE && message.value != currentSong.title) ||
        (message.type == Type.ARTIST && message.value != currentSong.artist)) {
        emit(currentSong.copy())
     }
    // Do updates.  *** This feels wrong, like a running state....
    when(message.type) {
        // stuff that warrants a full new song
        Type.ARTIST->currentSong = Song(
            artist = message.value,
            title = currentSong.title,
        )
         Type.TITLE->currentSong = Song(
             artist=currentSong.artist,
             title=message.value,
         )
        // stuff that DOESN'T warrant a full new song
        Type.FILE->currentSong.files.add(message.value)
    }
    // stuff we should always do
    currentSong.length = Duration.between(currentSong.start, Instant.now())
}

There is nothing wrong in keeping a state by a flow operator. Many operators do this: debounce(), distinctUntilChanged(), etc.

But your data structure / data flow is really strange. It doesn’t have any start/end and by looking at your code it seems like this data stream doesn’t at all have any clearly defined structure. You basically guess how to parse it. Also, it is even more complicated because you use immutable data holder for data that you actually need to mutate.

I think your case would be problematic no matter if you use flows or simple collections.