return — 프로시저에서 반환, 또는 스크립트의 반환 코드 설정
return — 프로시저에서 반환, 또는 스크립트의 반환 코드 설정
프로시저가 작업을 마치고 호출자에게 결과를 돌려주는 명령이 바로 return이에요. 단순히 값을 반환하는 것이 전부가 아니라, 오류나 break/continue 같은 특별한 반환 코드를 만들어 내는 데도 쓰여요. Tcl에서 프로그램의 흐름을 제어하는 핵심 개념 가운데 하나예요.
출처: 문서
본문
문법
return ?result?
return ?-code code? ?result?
return ?option value ...? ?result?
동작 방식
가장 간단한 사용법에서 return은 프로시저 본문에서 옵션 없이 사용돼 프로시저의 호출자에게 즉시 제어권을 돌려줘요. result 인자가 주어지면 그 값이 호출자에게 전달되는 프로시저의 결과가 돼요. result가 지정되지 않으면 빈 문자열이 프로시저의 결과로 호출자에게 반환돼요.
return은 source 명령이 평가하는 스크립트 파일 안에서도 비슷한 기능을 해요. source가 파일 내용을 스크립트로 평가할 때 return 호출은 스크립트 평가를 즉시 중단시키고, result 값(또는 빈 문자열)이 source 명령의 결과로 반환돼요.
특수 반환 코드(EXCEPTIONAL RETURN CODES)
프로시저의 결과뿐 아니라 프로시저의 반환 코드도 -code 옵션을 통해 return으로 설정할 수 있어요. 보통 -code 옵션을 지정하지 않으면 프로시저는 정상적으로 반환해요. 하지만 -code 옵션으로 프로시저에서 특수한 반환을 만들어 낼 수 있어요.
code는 다음 값 중 하나일 수 있어요:
ok(또는 0) — 정상 반환: 옵션을 생략한 것과 같음. 반환 코드는 0 (TCL_OK).error(또는 1) — 오류 반환: 반환 코드는 1 (TCL_ERROR). 프로시저 명령은 호출 문맥에서error명령의 결과처럼 동작해요.return(또는 2) — 반환 코드는 2 (TCL_RETURN). 프로시저 명령은 호출 문맥에서 인자 없는return명령처럼 동작해요.break(또는 3) — 반환 코드는 3 (TCL_BREAK). 호출 문맥에서break명령처럼 동작해요.continue(또는 4) — 반환 코드는 4 (TCL_CONTINUE). 호출 문맥에서continue명령처럼 동작해요.value—value는 정수여야 하며 현재 프로시저의 반환 코드로 반환돼요.
프로시저가 호출자로부터 잘못된 인자를 받았음을 알리고 싶으면 result를 적절한 오류 메시지로 설정한 return -code error를 사용할 수 있어요. 그 외에는 return -code 옵션의 사용은 대부분 새 제어 구조를 구현하는 프로시저로 제한돼요.
반환 옵션(RETURN OPTIONS)
결과와 반환 코드 외에도 Tcl에서 명령 평가는 반환 옵션 딕셔너리(return options dictionary)를 생성해요. 일반적인 사용에서 return에 인자로 주어진 모든 옵션-값 쌍은 이 딕셔너리의 항목이 되고, 아래에 명시된 경우를 제외하면 어떤 값이든 허용돼요. catch 명령으로 스크립트 평가에서 비롯된 반환 코드, 결과, 반환 옵션 딕셔너리 등 이 모든 정보를 포착할 수 있어요.
Tcl이 특별히 인식해 처리하는 다른 반환 옵션은 다음과 같아요:
-errorcode list—-code옵션의 값이 TCL_ERROR일 때만 특별 처리를 받아요. 그때list값은 오류에 대한 추가 정보로, 프로그램이 추가 처리할 수 있도록 Tcl 리스트로 제공돼요.-code error옵션이 주어질 때return에-errorcode옵션이 없으면 반환 옵션 딕셔너리의-errorcode항목 값이 기본값NONE으로 설정돼요.-errorcode반환 옵션은 전역 변수errorCode에도 저장돼요.-errorinfo info—-code값이 TCL_ERROR일 때만 특별 처리.info는 초기 스택 트레이스로, 오류가 발생한 문맥에 대한 추가 정보를 인간 독자에게 제공하기 위한 것이에요. 스택 트레이스는 전역 변수errorInfo에도 저장돼요.-code error가 주어질 때-errorinfo가 없으면 Tcl이 자신의 초기 스택 트레이스 값을-errorinfo항목에 제공해요.-errorstack list—-code값이 TCL_ERROR일 때만 특별 처리.list는 초기 오류 스택으로, 각 proc 레벨에 전달된 실제 인자 값을 기록해요. 오류 스택은info errorstack으로도 접근할 수 있어요.-level level—-level과-code옵션은 함께 동작해, 현재 평가 중인 명령 중 하나가 반환할 반환 코드를 설정해요.level값은 호출 스택의 레벨 수를 나타내는 비음의 정수여야 해요. 현재 평가 중인 명령의 반환 코드가code여야 하는 스택 위의 레벨 수를 정의해요.-level이 없으면 기본값은 1로,return이 현재 프로시저가 그 호출자(호출 스택 1레벨 위)에게 반환하는 반환 코드를 설정해요.-options options—options값은 유효한 딕셔너리여야 해요. 그 딕셔너리의 항목들은return명령에 대한 추가 옵션-값 쌍으로 취급돼요.
반환 코드 처리 메커니즘(RETURN CODE HANDLING MECHANISMS)
Tcl에서 반환 코드는 프로그램 흐름을 제어하는 데 사용돼요. Tcl 스크립트는 Tcl 명령의 시퀀스예요. 각 명령 평가가 TCL_OK 반환 코드를 반환하는 한 평가는 스크립트의 다음 명령으로 계속돼요. 명령 평가가 반환한 특수 반환 코드(비-TCL_OK)는 다음 명령으로의 흐름을 중단시켜요. 스크립트 평가가 중단되고, 명령의 특수 반환 코드가 전체 스크립트 평가의 반환 코드가 돼요. 이것이 스크립트 평가 중 오류가 중단과 호출 스택의 풀림(unwinding)을 일으키는 메커니즘이에요. break, continue, return 같은 명령이 모든 명령을 순서대로 평가하지 않고 스크립트 평가를 종료시키는 메커니즘이기도 해요.
Tcl의 내장 명령 중 일부는 기능의 일부로 스크립트를 평가해요. 이 명령들은 특수 반환 코드를 활용해 특별한 기능을 가능하게 해요. 예를 들어 while, for, foreach 같은 루프를 제공하는 내장 Tcl 명령은 루프의 본문인 스크립트를 평가해요. 루프 본문 평가가 TCL_BREAK나 TCL_CONTINUE 반환 코드를 반환하면, 루프 명령은 break와 continue 명령이 루프에서 갖는 문서화된 해석을 제공하도록 반응할 수 있어요.
프로시저 호출도 스크립트(프로시저 본문)의 평가를 수반해요. 프로시저 호출은 프로시저 본문 평가가 TCL_RETURN 반환 코드를 반환할 때 특별 처리를 제공해요. 그 상황에서 반환 옵션 딕셔너리의 -level 항목이 감소돼요. 감소 후 -level 값이 0이면 -code 항목의 값이 프로시저의 반환 코드가 돼요. 감소 후 -level 값이 여전히 0보다 크면 프로시저의 반환 코드는 TCL_RETURN이에요. 프로시저 호출이 다른 프로시저의 본문 평가 중 일어났다면, 이 과정은 호출 스택 위로 반복되며 각 레벨에서 -level 값을 감소시켜, code가 호출 스택 위 level 레벨 위의 현재 명령 레벨의 반환 코드가 되게 해요. source 명령도 TCL_RETURN 반환 코드에 대해 같은 처리를 수행해요.
return 명령 자체의 반환 코드가 프로시저 호출에 의한 이 특별 처리를 촉발해요. return에 -level 0 옵션이 주어지면 return 명령 자체의 반환 코드가 -code 옵션의 값(기본값 TCL_OK)이 돼요. -level 옵션의 다른 값(기본값 1 포함)은 return 명령 자체의 반환 코드가 TCL_RETURN이 되게 해, 둘러싼 프로시저에서의 반환을 촉발해요.
예제
return으로 프로시저에서 반환해 프로시저 본문을 중단시키는 간단한 예:
proc printOneLine {} {
puts "line 1" ;# 이 줄은 출력됨
return
puts "line 2" ;# 이 줄은 출력되지 않음
}
return으로 프로시저가 반환하는 값을 설정하는 예:
proc returnX {} {return X}
puts [returnX] ;# "X" 출력
return -code error로 잘못된 인자를 보고하는 더 완전한 예:
proc factorial {n} {
if {![string is integer $n] || ($n < 0)} {
return -code error \
"expected non-negative integer,\
but got \"$n\""
}
if {$n < 2} {
return 1
}
set factor [factorial [expr {$n - 1}]]
set product [expr {$n * $factor}]
return $product
}
break를 대체하는 프로시저:
proc myBreak {} {
return -code break
}
-level 0 옵션으로 return 자체가 interp alias의 도움으로 break를 대체할 수 있어요:
interp alias {} Break {} return -level 0 -code break
catch와 return -options로 잡은 오류를 다시 던지는 예:
proc doSomething {} {
set resource [allocate]
catch {
# 오류를 일으킬 수 있는 긴 연산 스크립트
} result options
deallocate $resource
return -options $options $result
}
마지막으로 반환 옵션을 고급으로 사용해 return 자체를 대체하는 프로시저를 만드는 예:
proc myReturn {args} {
set result ""
if {[llength $args] % 2} {
set result [lindex $args end]
set args [lrange $args 0 end-1]
}
set options [dict merge {-level 1} $args]
dict incr options -level
return -options $options $result
}
더 알아보기
break,continue: 루프 제어catch,error,errorCode,errorInfo: 오류 처리proc,source: 프로시저와 스크립트 평가throw,try: 예외 처리 확장