tescoder
tescoder

Reputation: 33

get key value from tcl dict with a default value

Very new/rusty with TCL here :-(. I am stuck with tcl 8.6 and can't take advantage of tcl 8.7 feature of getwithdefault on a dict.

Tried the following and get error saying "frameLen" is not part of the dict. But I thought the ternary operator should have skiped the part on [dict get $pktBlock frameLen]. What did I do wrong? Thanks!

package require json

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

Upvotes: 1

Views: 1369

Answers (3)

Shawn
Shawn

Reputation: 52529

My version (Different syntax than what's slated for 8.7; the default value is optional here and defaults to an empty string):

# 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]
}

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 247022

It's not too difficult to implement this feature in plain 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
    }
}

This can be added as a dict subcommand like this:

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

So that:

set frameLen [dict getdef $pktBlock frameLen 256]

Upvotes: 2

tescoder
tescoder

Reputation: 33

Turned out I had a wrong spelling. I intended to have dict exists $pktBlock frameLen but ended up using framelen.

Case is VERY important. Hope this could be a lesson for those who are stuck

Upvotes: 1

Related Questions