일반적으로 함수 호출 방식에는 두 가지가 있습니다. 하나는 "값 호출(call by value)"이고, 다른 하나는 "참조 호출(call by reference)"입니다. 최근의 프로그래밍 언어는 값 호출이 주류이며, C 언어의 함수나 Tcl의 프로시저가 그 예입니다. 반대로 Perl의 서브루틴은 참조 호출 방식입니다.
값 호출의 개념은 매우 간단합니다.
- 전달받을 데이터를 저장할 변수(가인수, 매개변수)를 준비한다.
- 데이터를 인수에 대입한다.
- 함수(프로시저) 실행이 끝나면 가인수를 폐기한다.
"가인수(매개변수)"란, 프로시저를 정의할 때 데이터를 전달받기 위해 설정하는 변수입니다. 이에 반해, 실제로 프로시저를 호출할 때 전달되는 인수를 "실인수"라고 합니다. 값 호출의 경우, 가인수는 지역 변수로 취급됩니다.
그런데 값 호출로는 불가능한 처리가 있습니다. 예를 들어, 변수의 값을 교환하는 프로시저 swap을 생각해봅시다. 아래의 프로그램을 보세요.
리스트: 값의 교환 (잘못된 예)
proc swap {a b} {
set temp $a
set a $b
set b $temp
}
# x와 y의 값 교환
proc foo {} {
set x 10
set y 20
puts "$x $y"
swap $x $y
puts "$x $y"
}
foo를 실행하면 다음과 같은 결과가 나옵니다.
% foo
10 20
10 20
프로시저 swap에서는 인수 a, b의 값을 교환하지만, 변수 x, y의 값은 swap을 호출한 후에도 교환되지 않습니다. 이유는 간단합니다. swap의 인수 a, b는 지역 변수이므로 swap 내에서 a와 b를 교환해도 foo의 변수 x와 y를 교환하는 것이 아니기 때문입니다. 프로시저가 값 호출 방식이기 때문에 다른 프로시저의 지역 변수에 접근할 수 없습니다.
Tcl에서 swap을 구현하려면 upvar 명령을 사용합니다.
upvar [level] otherVar1 myVar1 otherVar2 myVar2 ...
upvar는 다른 프로시저에서 사용 중인 지역 변수(otherVar)를 실행 중인 프로시저에서 사용할 지역 변수(myVar)와 연결해줍니다. 그 결과, myVar에 접근하는 것은 otherVar에 접근하는 것과 같습니다. 즉, myVar의 값을 읽으면 그 값은 otherVar의 값이고, myVar의 값을 변경하면 otherVar도 그 값으로 바뀝니다.
프로시저 지정에는 level을 사용합니다. 기본값은 -1로, 실행 중인 프로시저를 호출한 프로시저가 됩니다. 예를 들어, 다음과 같이 프로시저를 호출했다고 합시다.
foo1 -> foo2 -> foo3 -> foo4
level -3 -2 -1 upvar
(그림: level의 지정)
foo4에서 upvar를 사용할 경우, level이 -1이면 foo3이 대상이 되고, -2면 foo2, -3이면 foo1이 대상이 됩니다. 그리고 foo1에서 upvar를 사용하면 전역 변수를 접근하게 됩니다.
리스트: 값의 교환
proc swap {a b} {
upvar $a aa $b bb
set temp $aa
set aa $bb
set bb $temp
}
upvar를 사용하면 swap을 다음과 같이 프로그래밍할 수 있습니다.
swap을 호출할 때는 변수명을 전달해야 한다는 점에 주의하세요. swap에서는 전달받은 변수명과 프로시저 내에서 사용할 지역 변수를 upvar로 연결합니다. 인수 a로 전달받은 변수는 aa에, 인수 b로 전달받은 변수는 bb에 연결됩니다. 예를 들어, 다음 예시를 보세요.
proc foo {} {
set x 10
set y 20
puts "$x $y"
swap x y
puts "$x $y"
}
% foo
10 20
20 10
이 경우, aa에 접근하는 것은 foo 내의 지역 변수 x를, bb에 접근하는 것은 y를 접근하는 것과 같습니다. 이렇게 해서 foo의 지역 변수 x와 y의 값을 교환할 수 있습니다.
'Tcl & Tk > 팁 (Tip)' 카테고리의 다른 글
Tcl의 로고가 깃털인 이유 (0) | 2025.09.05 |
---|---|
Tcl 8.5의 임의 정밀도 계산 (0) | 2025.09.01 |
namespace ensemble (0) | 2025.09.01 |
메가위젯(Megawidget) 이란? (0) | 2025.08.18 |
파스텔 컬러 변환 (0) | 2025.07.18 |