http://pascal.scheffers.net/software/
Tcl8.5부터 추가된 새로운 데이터 형인 dict 커맨드에 대해서 알아봅니다. dict는 리스트와 배열의 중간 정도라 생각할 수 있습니다. dict는 리스트를 구조체처럼 사용하거나, 배열을 proc의 리턴값으로 돌려줄 수 있는 예전 버전에서의 불편한 요소들을 해소하기 위해 추가된 커맨드입니다. dict는 해쉬(hash)로 되어 있는 배열보단 빠를 것 같지만, Tcl의 경우 리스트도 어느 경우 배열보다 빠른 경우가 있기 때문에, list/array/dict 3개를 비교해 보지 않으면 알 수는 없을 것입니다. 우선 Tcl8.5에 기본으로 추가된 dict를 테스트해보기 전에, 정식 릴리즈가 되지 않은 불안정한 상태에서 8.5 버전의 dict 대신, 8.4 버전으로도 릴리즈 된 비교적 안정화 버전의 dict를 대상으로 테스트해봅니다. (8.5 버전의 dict와 동일한 기능입니다.)
옵션 목록
옵션 | 설명 |
---|---|
dict append varName key ?value ...? | key 값의 끝에 value를 추가. |
dict create ?key value ...? | 새로운 dict 생성. |
dict exists dictionary key ?key ...? | key가 존재 하는지 검사. |
dict filter dictionary filterType ... | dict를 필터(filter)링 한다. |
dict for {keyVar valueVar} | dictionary script foreach |
dict get dictionary ?key key ...? | key의 값을 돌려 준다. |
dict incr varName key ?increment? | incr과 동일한 의미이며, key 값을 늘린다. |
dict info dictionary | dict의 내부 정보를 돌려 준다. |
dict keys dictionary ?pattern? | key의 리스트를 돌려 준다. |
dict lappend varName key ?value ...? | key의 값을 리스트에 추가. |
dict merge ?dictionary ...? | 여러개의 dict를 연결하여 돌려 준다. |
dict remove dictionary ?key ...? | key의 페어(pair)를 삭제한 dict를 돌려 준다. |
dict replace dictionary ?key value ...? | key를 value로 치환한후의 값을 돌려 준다. |
dict set varName key ?key ...? value | key에 value를 세트. |
dict size dictionary | dict의 크기를 돌려 준다. |
dict update varName key varName ?key varName ...? | script key를 varName에 할당(assign) 하여 코드를 실행(8.5 전용) |
dict unset varName key ?key ...? | key의 페어(pair)를 삭제. |
dict values dictionary ?pattern? | 값의 리스트를 돌려 준다. |
dict with varName ?key ...? | script dict의 이름 공간(namespace)에서 코드를 실행(8.5 전용) |
기본적인 사용방법
package require dict
set d [dict create name inhak-min]
dict를 생성시에는 name키에 inhak-min과 비슷한 값으로 지정을 합니다.
package require dict
set d [dict create name inhak-min]
dict set d age 28
dict set d level 10
그리고 생성된 dict 변수 d에 새로운 키와 값을 지정하는 것은 위와 같이 합니다.
네스팅(Nesting)
dict는 다른dict를 포함할 수 있습니다. 이것은 array와는 다른 점입니다.
package require dict
set d [dict create a [dict create aa 0] b 1]
puts $d
=> a {aa 0} b 1
puts [dict get $d a]
=> aa 0
puts [dict get $d a aa]
=> 0
그리고 하나의 키에 대응하는 값은 단순 문자열뿐만이 아닌 리스트도 가능합니다.
package require dict
set d [dict create a 0 b 1]
dict set d c {}
dict set d c cc 2
puts [dict get $d c]
=> cc 2
혹은
dict set d c cc 2
부분을 다음과 같이 고칠수도 있습니다.
dict set d c [list cc 2]
편리한 기능
array는 프로시져의 리턴값으로 돌려줄 수 없기 때문에,
array get a
와
array set a
등을 사용하거나 혹은 upvar를, 또는 global 변수를 사용하여 액세스를 해야만 합니다.
proc test {alist} {
array set arr $alist
....
return [array get arr]
}
array set ga {hoge 0 fuga 1}
test [array get ga]
proc test {alist} {
upvar $alist arr
....
}
array set ga {hoge 0 fuga 1}
test ga
그러나 편리하게도 dict는 위와같이 프러시저의 리턴값으로 돌려줄 수 있습니다.
package require dict
proc test {} {
return [dict create hoge 0 fuga 1]
}
puts [test]
개인적인 생각은 현재의 array 기능을 제거하고, dict로 전부 통일시키는 쪽이 좋을 것 같습니다. (호환성을 생각한다면 유지하는 것도 괜찮을 것 같긴 합니다.)
filter 기능
필터는 key, value, script와 같이 3가지 방향을 제시합니다.
- dict filter dict key pattern
- dict filter dict value pattern
- dict filter dict script {keyName valueName} body
package require dict
dict filter {aa 0 ab 1 ac 2 ba 3 bb 4 bc 5} key a*
=> ac 2 aa 0 ab 1
dict filter {n1 min n2 kim n3 park n4 byun} value mi*
=> n1 min
dict filter {hyundai 1.15 kia 3.05 nissan -0.71} script {k v} {expr $v>0}
=> hyundai 1.15 kia 3.05
update 기능 (Tcl8.5 버전만 가능)
값의 변경
set info {name hyundai code 7203}
dict update info name nameVar code codeVar {
set nameVar [string toupper $nameVar]
set codeVar ($codeVar)
}
puts $info
=> name HYUNDAI code (7203)
키 추가
set info {name hyundai code 7203 price 5280}
dict update info per perVar {
set perVar 15
}
puts $info
=> name hyundai per 15 price 5280 code 7203
키 삭제
set info {name hyundai code 7203 price 5280}
dict update info price priceVar {
unset priceVar
}
puts $info
=> name hyundai code 7203
body 내에서 dict에 액세스 하는 것도 가능합니다. price의 두 배의 값을 price2란 키로 만들어 대입해보겠습니다.
set info {name hyundai code 7203 price 5280}
dict update info price2 price2Var {
set price2Var [expr 2 * [dict get $info price]]
}
puts $info
=> price2 10560 name hyundai price 5280 code 7203
with 기능 (8.5 버전만 가능)
set info {name hyundai code 7203 price 5280}
dict with info {
puts name=$name
puts code=$code
puts price=$price
}
=> name=hyundai
code=7203
price=5280
dict update와 같이 대응되는 키를 삭제 시에는 다음과 같이 합니다.
set info {name hyundai code 7203 price 5280}
dict with info {
unset name
}
puts $info
=> price 5280 code 7203