Non final variables in lambda

Hi All,

I’ve been trying to figure out how to do this the right way but cannot any help would be appreciated. I have 2 Group Items that are related. The first is a String item that has the value of the spoken Amazon phrase. The second is the timestamp of that phrase for the first item.

I am filtering the members of first group to only provide items that have specific key words. I can get the corresponding time that the phrase was said in the associated item, but what I am trying to get is the latest time of the filtered list. The only way I can think of doing this is finding the max value as I iterate through the first list. This causes me to use non final variables inside the for loop. The code works, but it throws warnings in VSC. Is there a way to get this to work without the warnings?

    gLastPhrase.members.filter( i |  (i.state.toString.contains("turn") || i.state.toString.contains("set"))).forEach[ i |  

          val timeItem = ScriptServiceUtil.getItemRegistry.getItem( + "Time")
          val Number currentMillis = if (timeItem != UNDEF || timeItem.state != NULL ) (timeItem.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli else 0
           if (currentMillis >= maxMillis) {
            maxMillis = currentMillis 
            maxItem = i as GenericItem


Thanks for any help.


Break it up into multiple steps.

  1. Get the Items with “turn” or “set” in the state.
    val turnItems = gLastPhrase.members.filter[ i | i.state.toString.contains("turn") || i.state.toString.contains("set") ]
  1. Sort the Items by the state of their associated Time Item and get the most recent one.
    val mostRecentTime = turnItems.sortBy[ i | ScriptServiceUtil.getItemRegistry.getItem( + "Time").state ].tail

Of course you could probably string this all together into one line, but it’s probably easier to follow if kept separate like this. I’m going from memory so there might be typos in the above.

Notice I didn’t actually answer your specific question. That’s because this is an XY Problem, using a var inside your forEach isn’t the way you want to go anyway. But to answer your specific question, you can’t.

You rock!!! Thank you so much. This was frustrating me for a while now and I just broke down to ask. I was so fixated on the for loop that I totally forgot to simply create a filtered list and act on that list.

Thanks again for such a quick a reply.


Just a quick update for everyones’ benefit. The syntax that works for the second part is:

val mostRecentTime = turnList.sortBy[ i | (ScriptServiceUtil.getItemRegistry.getItem( + "Time").state as DateTimeType).zonedDateTime.toInstant.toEpochMilli ].last

Thank you again,

1 Like

I love when they are not consistent. It’s head to get the first element so of course they wouldn’t choose tail for the last element. :wink: Thanks for coming back with the correction.