Here's a simple bit of code to extend any [ensemble]-like command by means of tcl8.5's [namespace ensemble] command. [CMcC] 6Mar2006 [Larry Smith]: [stacking] does a similar job. ====== package provide extend 1.0 package require Tcl 8.5 # extend a command with a new subcommand proc extend {cmd body} { if {![namespace exists ${cmd}]} { set wrapper [string map [list %C $cmd %B $body] { namespace eval %C {} rename %C %C::%C namespace eval %C { proc _unknown {junk subc args} { return [list %C::%C $subc] } namespace ensemble create -unknown %C::_unknown } }] } append wrapper [string map [list %C $cmd %B $body] { namespace eval %C { %B namespace export -clear * } }] uplevel 1 $wrapper } ====== ---- Here's the [file] command extended with '''newer''' and '''newerthan''' subcommands: ====== extend file { proc newer {a b} { return [expr {[file mtime $a] > [file mtime $b]}] } proc newerthan {mtime path} { return [expr {[file exists $path] && ([file mtime $path] > $mtime)}] } } ====== Here's the [dict] command extended with the '''modify''' subcommand: ====== # extra useful dict commands extend dict { proc modify {var args} { upvar 1 $var dvar foreach {name val} $args { dict set dvar $name $val } } } ====== ---- [LV] So, this seems like a nice bit of functionality. Would it be useful enough to include either in Tcl itself or at least [Tcllib]? [Napier] I really like ES6 Javascripts capabilities to work with objects such as "const { key1, key2 } = myObject", so I decided to give myself similar functionality with a "dict gets" command. One thing I am not sure of, is if setting an empty string is the proper thing to do when a value doesn't exist. I would like to handle it similar to javascript, but tcl doesn't have a "null" option which could be used to default to false I know this is somewhat similar to dict update or dict with but the syntax is a bit simpler and it's designed for it's exact purpose, except that it only unpacks the requested keys and will create the variables so they may be used without [info exists] in cases that is too verbose. The resulting operation with extend: ====== set tempDict [dict create foo fooVal bar barVal] dict gets $tempDict foo bar rawr puts $foo ; # % fooVal puts $bar ; # % barVal puts $rawr ; # % "" ====== and the code: ====== extend dict { proc gets {var args} { foreach val $args { upvar 1 $val $val if {[dict exists $var $val]} { set $val [dict get $var $val] } else { set $val {} } } } } ====== ---- ''quick hacks'' ? ---- [AMG]: See also my [[dict getnull]] example in [[[dict get]]]. ---- [samoc]: oclib.tcl[https://github.com/samoconnor/oclib.tcl] has a similar "extend_proc" [https://github.com/samoconnor/oclib.tcl/blob/master/oclib/oc_ensemble-1.0.tm#L17] command. ---- In a [comp.lang.tcl] posting dated Fri, 04 Apr 2014 09:25:30 [DKF] posted an example of using the ensemble's `-unknown` parameter to lazily apply extensions. A version of [extend] using this technique: ====== proc extend {ens script} { namespace eval $ens [concat { proc _unknown {ens cmd args} { if {$cmd in [namespace eval ::${ens} {::info commands}]} { set map [namespace ensemble configure $ens -map] dict set map $cmd ::${ens}::$cmd namespace ensemble configure $ens -map $map } return "" ;# back to namespace ensemble dispatch ;# which will error appropriately if the cmd doesn't exist } } \; $script] namespace ensemble configure $ens -unknown ${ens}::_unknown } ====== Note that new extensions defined in this way will not appear in the ensemble's map until they are used, so the default error message is misleading. <> Example