3

I'm trying to convert the following Java code to Kotlin in an idiomatic way:

for (Group group : groups) {
    String groupName = group.getName();
    if (groupName == null) {
        warn("Group name is null for group " + group.getId());
        continue;
    }
    ...
}

I tried the following

for (group in groups) {
    val groupName = group.name ?: run {
        warn("Group name is null for group ${group.id}!")
        continue
    }
    ...
}

However this will not compile with the error:

'break' or 'continue' jumps across a function or class boundary

So my question is, is there a better way to write this in Kotlin?

Bhuvanesh BS
  • 13,474
  • 12
  • 40
  • 66
idunnololz
  • 8,058
  • 5
  • 30
  • 46

4 Answers4

1

Normally continue can be also emulated via ::filter.

But since in this case you need also a warning, this makes the classic for the best solution.

However there are some alternatives.

groups.filter { group -> when(group.name) {
        null -> {
            warn("Group name is null for group ${group.id}!")
            false
        }
        else -> true
    }.for Each {
        ...
    }
}

Or use return@forEach.

But again, in this case a classic for is the best solution

elect
  • 6,765
  • 10
  • 53
  • 119
0

Without modifying your code too much, just use the good old if

for (group in groups) {
    val groupName = group.name

    if (groupName == null) {
        warn("Group name is null for group ${group.id}!")
        continue
    }
    ...
}
guenhter
  • 11,255
  • 3
  • 35
  • 66
0

The same java code can be implemented like this.

for (group in groups) {
    val groupName = group.name
    if(groupName == nul){
      warn("Group name is null for group ${group.id}!")
      continue
    }
    ...
}

However, you can continue to top loop or other loops in Kotlin by giving labels.

loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) continue@loop
    }
}

Update:

You can't implement continue in lambda functions. But you can use return alternatively.

fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // local return to the caller of the lambda, i.e. the forEach loop
        print(it)
    }
    print(" done with explicit label")
}

Output:

1245 done with explicit label

Reference: https://kotlinlang.org/docs/reference/returns.html

Bhuvanesh BS
  • 13,474
  • 12
  • 40
  • 66
0

I think I found a very satisfying and idiomatic solution:

groups.forEach { group ->
    val groupName = group.name ?: run {
        warn("Group name is null for group ${group.id}!")
        return@forEach
    }
    ...
}
idunnololz
  • 8,058
  • 5
  • 30
  • 46