대부분의 언어와 마찬가지로 Kotilin에는 흐름에 대한 제어를 위한 표현이 있습니다.
- return : 수행하던 구문에서 바로 리턴
- break : 반복수행 하던 구문 중단
- continue : 반복 구문 계속 수행
예제를 통해 알아보겠습니다.
fun main() {
println("1에서 10까지의 수 하나를 입력하세요.")
val value = readln().toInt()
for(i in 1..10) {
if(i/value == 1) {
println("입력하신 값은 $i 입니다.")
break
}
}
}
숫자를 입력받아 어떤 수인지 찾는 프로그램이라고 가정했습니다.
물론 입력 받은 value를 바로 출력하면 되지만, value의 값이 미지의 값이라고 가정하고 진행합니다.
for 반복문을 통해 i를 value로 나누어 1이면 같은 수겠지요? 그 수를 출력합니다.
출력했다는 이야기는 목적을 달성했다는 이야기이고 더 남은 반복문을 실행할 필요는 없습니다.
bareak를 통해 for 반복문에서 빠져 나옵니다.
위 예제에서 for 문을 별도 function으로 구현해 보겠습니다.
fun main() {
println("1에서 10까지의 수 하나를 입력하세요.")
val value = readln().toInt()
findNumber(value)
}
fun findNumber(value :Int) {
for(i in 1..10) {
if(i/value == 1) {
println("입력하신 값은 $i 입니다.")
return
}
println("입력하신 값은 $i는 아닙니다.")
}
println("프로그램을 종료합니다.")
}
위 예제에서는 findNumber라는 function을 통해 value 값을 찾는 프로그램 입니다.
for 반복문을 수행하면서 if문의 조건이 true가 되면 출력을 하고 return합니다.
그럼 실제 실행해보면 결과는 어떨까요?
4를 입력해 4라는 것을 찾은 후 반복문에서 빠져나왔습니다.
그런데 여기서 보면 반복문 밖에 있는 출력문이 수행되지 않은 것을 알 수 있습니다.
반복문만이 아니라 function 자체에서 빠져나왔기 때문입니다.
그렇다면 어떻게 하면 for 반복문에서만 빠져 나올 수 있을까요?
return을 break로 변경한 실행 결과입니다.
break는 for 반복문에서만 빠져나와 아래에 있는 구문이 실행되었습니다.
Kotlin의 모든 표현식에는 Label(레이블)이 표시될 수 있습니다. 레이블은 abc@ 또는 fooBar@와 같이 식별자 뒤에 @ 기호가 붙는 형식을 갖습니다. 표현식에 레이블을 지정하려면 표현식 앞에 레이블을 추가하면 됩니다.
레이블은 어디에 쓰일까요?
fun main() {
for(i in 1..3) {
println("${i} 단입니다.")
for (j in 1..3) {
println("$i X $j = ${i*j}" )
if(j==2) {
break
}
}
}
}
위 예제는 두개의 중첩 for 반복문이 있습니다. break 는 어디서 빠져나가는 것일까요?
안쪽의 for문에서 빠져나왔습니다.
그렇다면 밖의 for 구문에서 빠져나오고 싶다면 어떻게 해야할까요? 이런 경우 사용하는 것이 레이블입니다.
아래 예제로 확인해보겠습니다. 첫번째 반복문에 firstloop이라는 label을 달았고 break@firstloop라고 명시하여 첫번째 레이블 표현식에서 빠져나가도록 지정하였습니다.
fun main() {
// 첫번째 for 구문에 firstloop이라는 레이블을 달았습니다.
firstloop@ for(i in 1..3) {
println("${i} 단입니다.")
for (j in 1..3) {
println("$i X $j = ${i*j}" )
if(j==2) {
// 레이블 firstloop에서 빠져나가라고 지시합니다.
break@firstloop
}
}
}
}
Returns to labels
Kotlin에서는 함수들을 중첩해서 사용할 수 있습니다. return을 사용하면 외부 함수에서 반화하여 빠져나올 수 있습니다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // 조건을 만족하면 반환합니다. 즉, foo ()함수에서 빠져 나갑니다.
print(it)
}
println("이 문구는 프린트 되지 않습니다.")
}
만약 List에 3이 없다면 println이 실행됩니다.
List에 3이 있어도 println을 실행하려면 어떻게 해야할까요?
break 구문과 유사하게 label을 사용하여 landa 표현식에서만 빠져나올 수 있습니다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // lamda 호출자에 대한 로컬 반환
print(it)
}
println("이제 프린트 됩니다.")
}
좀더 편리하게 label을 지정하지 않고 묵시적 label을 사용하기도 합니다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda - the forEach loop
print(it)
}
println(" 이제 프린트 됩니다.")
}
또, lamda 표현식을 익명 함수(anonymous function)으로 바꿀 수 있으며, 이때는 익명 함수 자체에서 반환 됩니다.
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return // local return to the caller of the anonymous function - the forEach loop
print(value)
})
println(" done with anonymous function")
}
이때에도 println 문은 실행됩니다.
break 구문에 직접적으로 상응하지는 않지만, 다른 중첩 lamda를 추가하고 로컬이 아닌곳에서 반환하여 시뮬레이션 할 수는 있습니다.
fun foo() {
run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop // non-local return from the lambda passed to run
print(it)
}
}
print(" done with nested loop")
}
value를 return 할 수도 있습니다.
fun foo() {
val num = run loop@{
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@loop it// non-local return from the lambda passed to run
}
}
print(" $num done with nested loop")
}
실행 결과는 아래와 같습니다.
3 done with nested loop
'DEVELOPMENT > Kotlin' 카테고리의 다른 글
11. Kotlin, Ranges, Loops - for, while (0) | 2024.03.04 |
---|---|
10. Kotlin, Control flow - if, when (0) | 2024.03.03 |
9. Kotlin, Collections - List, Set, Map (0) | 2024.02.26 |
8. Kotlin, Basic Data Types - Arrays (0) | 2024.02.26 |
7. Kotlin, Basic Data Types - String (1) | 2024.02.26 |