使用默认值从 tcl 字典获取键值

get key value from tcl dict with a default value

非常new/rusty 在这里使用 TCL :-(。我被 tcl 8.6 困住了,无法在 dict 上利用 getwithdefault 的 tcl 8.7 功能。

尝试了以下操作并收到错误提示“frameLen”不是字典的一部分。但我认为三元运算符应该跳过 [dict get $pktBlock frameLen] 上的部分。我做错了什么? 谢谢!

package require json

set pktBlock [json::json2dict {{"frameLenn": 253}}]
set frameLen [expr [dict exists $pktBlock framelen] ?  [dict get $pktBlock frameLen]:  256 ]

原来我拼错了。我打算 dict exists $pktBlock frameLen 但最终使用 framelen.

大小写非常重要。希望这对那些被卡住的人来说是一个教训

在普通 Tcl 中实现此功能并不难:

#    dict getdef dictionaryValue ?key ...? key default
#
# This will be in Tcl 8.7 -- https://tcl.tk/man/tcl8.7/TclCmd/dict.htm

proc dict_getdef {dictValue args} {
    if {[llength $args] < 2} {
        error {wrong # args: should be "dict getdef dictValue ?key ...? key default"}
    }

    set default [lindex $args end]
    set keys [lrange $args 0 end-1]

    if {[dict exists $dictValue {*}$keys]} {
        return [dict get $dictValue {*}$keys]
    } else {
        return $default
    }
}

这可以作为 dict 子命令添加,如下所示:

set map [namespace ensemble configure dict -map]
dict set map getdef [namespace which dict_getdef]
namespace ensemble configure dict -map $map

这样:

set frameLen [dict getdef $pktBlock frameLen 256]

我的版本(与 8.7 的语法不同;此处的默认值是可选的,默认为空字符串):

# dict getdef dictValue -default arg path...
if {[::info commands ::tcl::dict::getdef] eq {}} {
    proc ::tcl::dict::getdef {dictionary args} {
        ::set def {}
        if {[lindex $args 0] eq "-default"} {            
            ::set args [::lassign $args _ def]
        }
        if {[exists $dictionary {*}$args]} {
            get $dictionary {*}$args
        } else {
            ::set def
        }
    }
    namespace ensemble configure \
        dict -map [dict replace [namespace ensemble configure dict -map] \
                       getdef ::tcl::dict::getdef]
}