Tcl/Tk 8.5 버전의 새로운 기능

admin의 아바타

Tcl/Tk8.5 에서는 많은 기능이 추가 되었지만, 그중 눈에 띄는 몇가지 기능을 소개합니다.

확장된 expr 커맨드

n승의 ** 연산자가 추가 되었습니다.

2.0 * pow($x,3)


2.0 * ($x ** 3)

처럼 사용할 수 있게 되었습니다.

리스트에 지정한 요소가 포함되어 있는지 아닌지를 판단하는 in및 그 반대의 ni 연산자가 추가되었습니다. lsearch 커맨드를 사용해도 되지만, 추가된 커맨드로 인하여 간단하게 코드를 작성할 수 있게 되었습니다.

set x {apple melon orange grape}

puts [expr {"apple" in $x}]
puts [expr {"apple" ni $x}]
puts [expr {"kiwi" in $x}]
puts [expr {"kiwi" ni $x}]

실행 결과는 아래와 같이 1이나 0이 출력됩니다.

1
0
0
1

자주 사용될 것 같은 예는 다음과 같은것 일지도 모릅니다.

set x {apple melon orange grape}

if {"apple" in $x} { puts 1 } else { puts 0 }

ni는 in의 반대의 처리를 합니다. 즉 리스트에 지정된 요소가 존재하지 않는다면 1을, 그렇지 않다면 0을 돌려줍니다.

{expand} 문법

변수에 리스트를 대입할때, $변수명의 형태로 사용합니다.
이것은 리스트의 형태이지만, 커맨드로부터 본다면 어디까지나 단일 문자열 인자로 인식되어 집니다. 그러나 {expand}를 인자의 $변수명앞에 붙이면, 리스트로 변환하여 대입해줍니다. 다음의 예로 설명하겠습니다.

set scoords {10 10}
set ecoords {60 40}
canvas .can -bg white
.can create rectangle $scoords $ecoords -fill "#800040" -outline white
pack .can

위의 예는 왼쪽위와 오른쪽밑의 좌표를 두개의 인자로 대입하려 합니다. 하지만 이 코드를 실행하면 에러가 발생합니다. canvas create rectangle 커맨드는, 네개의 인자 혹은 네개의 요소를 갖는 한개의 리스트만을 허용합니다.

그런데,

set scoords {10 10}
set ecoords {60 40}
canvas .can -bg white
.can create rectangle {expand}$scoords {expand}$ecoords -fill "#800040" -outline white
pack .can

라고 한다면, $coords, $ecoords의 전개된 결과가 대입됩니다.

.can create rectangle 10 10 60 40 -fill "#800040" -outline white

즉, 위와 같이 해석되므로, 원하던 결과를 얻을수 있습니다. 덧 붙여서,

set opts {
        -fill "#800040" -outline white
}
canvas .can -bg white
.can create rectangle 10 10 60 40 {expand}$opts
pack .can

{expand}는 보통의 Tcl 커맨드에서도 사용할 수 있습니다. 예를 들면 format 커맨드로 다음과 같이 인자에 대입하는 것도 할 수 있습니다.

set colorRGB [Image1 get $x $y]
set colorSPEC [format "#%02x%02x%02x" {expand}$colorRGB]

tclsh, source 커맨드의 확장

2바이트 언어권에 있어 새로운 기능이 등장했습니다. tclsh와 source 커맨드에 -encoding 옵션이 추가 됐습니다. -encoding euc-kr, -encoding cp949등과 같이 Tcl스크립트가 쓰여진 인코딩을 지정하면, 지정된 인코딩으로 읽어 들입니다.

puts "헬로우 월드"

위와 같은 demo.tcl 코드가 있다면,

tclsh -encoding cp949 demo.tcl

와 같이 사용합니다.
그리고 Unix에서는 아래와 같이 스크립트에 인코딩을 선언하여, 인코딩 변환의 수고를 덜수 있습니다.

#! /bin/sh
# ... \
exec tclsh -encoding cp949 "$0" "$@"
puts "헬로우 월드"

lassign 커맨드

리스트의 각 요소를 다른 변수에 한번에 대입시, 기존에는

set msg "Hello World"
foreach {var1 var2} $msg {}

와 같이 사용해야 했었습니다. 이런 동일한 처리를 간단히 처리하기 위해 lassign 커맨드가 추가 되었습니다.

set msg "Hello World"
lassign $msg var1 var2

또한, 리스트의 요소갯수가 변수의 수보다 적은 경우는, 남은 변수에 빈 문자열이 셋팅되며, 에러는 발생하지 않습니다.

lrepeat 커맨드

lrepeat 커맨드가 추가 되었습니다. 한번에 많은 요소를 갖는 리스트를 초기화 할수 있습니다.

set v [lrepeat 5 a]
puts $v
set v [string repeat a 5]
puts $v
set v [lrepeat 5 {a b c}]
puts $v

위의 예를 실행하면

a a a a a
aaaaa
{a b c} {a b c} {a b c} {a b c} {a b c}

의 결과가 나옵니다. lrepeatstring repeat의 서브 커맨드는 다릅니다.

checkbutton과 radiobutton의 세번째 상태

labelframe .lafa -text 간식
radiobutton .lafa.r1 -variable r -value 1 -text 빵
radiobutton .lafa.r2 -variable r -value 2 -text 귤
radiobutton .lafa.r3 -variable r -value 3 -text 매실
checkbutton .lafa.c1 -variable c1 -onvalue 1 -offvalue 2 -tristatevalue 0 \
        -text "바나나는 간식에 포함하지 않음."
pack {expand}[winfo children .lafa] -side left
set c1  0
set r   ""
pack .lafa

checkbutton과 radiobutton은 체크 한 것과 체크하지 않은 것의 두가지 상태뿐이었습니다. 추가된 상태는 초기 상태에서, 아직 사용자의 선택을 받지 않은 상태를 나타내는 세번째 상태입니다. 이것은 박스의 배경색이 회색으로, 변경 되어 있는 상태에서 표시됩니다. 새로운 옵션 -tristatevalue가 추가 되었고, -onvalue, -offvalue와 같은 값을 -tristatevalue에 지정해 두면, 변수에 값이 지정될때에 해당된 상태가 됩니다. radiobutton의 경우, 변수에 값이 셋팅되어 있지 않거나, radiobutton의 -value의 값이 모두 일치하지 않는 값이 셋팅되어 있을때, 세번째 상태가 됩니다.

lsearch 커맨드

lsearch에 -index, -subindices의 두 옵션이 추가되었습니다.

set banks {
    {100 국민 1 50}
    {050 기업 2 120}
    {120 농협 3 100}
    {070 외환 4 75}
}

# 1
puts [lsearch -index 1 $banks "기업"]
puts [lsearch -index 2 $banks "4"]

# 2
puts [lsearch -index 1 -subindices $banks "기업"]
puts [lsearch -index 2 -subindices $banks "4"]

# 3
puts [lsearch -index 1 -inline $banks "기업"]
puts [lsearch -index 2 -inline -subindices $banks "4"]

1
3
1 1
3 2
050 기업 2 120
070 외환 4 75

-index 옵션은 대상 리스트가 리스트의 리스트(list->list), 리스트의 리스트의 리스트(list->list->list)와 같은 경우에, 몇번째의 요소(컬럼)를 대상으로 검색을 할지를 정합니다. #1의 예는 -index 1 라고 하면, 각 리스트의 index=1의 요소, 즉 국민,기업,농협,외환중 '기업'은 두번째에 위치하기 때문에 1을 돌려줍니다. 마찬가지로 -index 2라고 하면, 세번째의 요소 1,2,3,4중에 4는 4번째에 위치하기 때문에 3을 돌려줍니다.

-subindices 옵션은 -index 옵션과 함께 지정해야만 하는 옵션입니다. 이 옵션은 -index로 지정된 해당 요소의 위치를 리스트로 돌려줍니다. 즉 2의 첫번째 예에서는 '1 1', 2의 두번째 예에서는 '3 2'를 돌려줍니다.

그리고 -index-inline을 함께 사용하면, 지정된 요소가 속해있는 리스트 전체를 돌려줍니다. 3의 첫번째 예에서는 '050 기업 2 120'을, 3의 두번째 예에서는 '070 외환 4 75'를 돌려줍니다.

lsort 커맨드

lsort 커맨드에 -indices 옵션이 추가됐습니다.

set a {A8 A10 A13 A101 A104}

puts [lsort -ascii $a]
puts [lsort -dictionary $a]

결과는 아래와 같습니다. (-ascii와 -dictionary의 차이는 Tcl 메뉴얼에 자세히 설명되어 있습니다. )

A10 A101 A104 A13 A8
A8 A10 A13 A101 A104

set a {A8 A10 A13 A101 A104}

puts [lsort -ascii -indices $a]
puts [lsort -dictionary -indices $a]

1 3 4 2 0
0 1 2 3 4

-indices 옵션은, sort된 결과의 각 요소가 원래 있던 인덱스의 리스트를 돌려줍니다.

set a {A8 A10 A13 A101 A104}

puts [lsort -ascii -indices $a]
puts [lsort -dictionary -indices $a]

puts [lindex $a 1]
puts [lindex $a 3]
puts [lindex $a 4]
puts [lindex $a 2]
puts [lindex $a 0]

1 3 4 2 0
0 1 2 3 4
A10
A101
A104
A13
A8

위와 결과를 보면, 'A10 A101 A104 A13 A8' 이 -ascii 순서로 sort되어 있는것을 알 수 있을것입니다.