The concept of Named Arguments as Dictionaries is to provide an extensible means to extend argument definitions to include rules and allow them to be given in any order, without introducing a major syntax change to proc. The project is maintained in a fossil repository [http://fossil.etoyoc.com/fossil/tip479] The Tcl implementation is reasonably trivial: ====== package provide tip479 0.1 proc ::@args {argdef argdict} { set result {} foreach {field info} $argdef { set variable $field set aliases {} if {[dict exists $info variable]} { set variable [dict get $info variable] } if {[dict exists $argdict $field]} { append result [list set $variable [dict get $argdict $field]] \n continue } if {[dict exists $info aliases]} { set aliases [dict get $info aliases] set found 0 foreach {name} $aliases { if {[dict exists $argdict $name]} { append result [list set $variable [dict get $argdict $name]] \n set found 1 break } } if {$found} continue } if {[dict exists $info default]} { append result [list set $variable [dict get $info default]] \n continue } set mandatory 1 if {[dict exists $info mandatory]} { set mandatory [dict get $info mandatory] } if {$mandatory} { error "$field is required" } } uplevel 1 $result } #replace the behavior of proc if {[info command ::_proc] eq {}} { rename ::proc ::_proc _proc ::proc {name arglist body} { set result {} if {[lindex [lindex $arglist end] 0] eq "args"} { if {[llength [lindex $arglist end]]==2} { set argspec [lindex [lindex $arglist end] 1] append result "::@args \{$argspec\} \$args" \; set arglist [lrange $arglist 0 end-1] lappend arglist args } } append result $body ::_proc $name $arglist $result } } ### # Named Procedures as new command ### proc ::@proc {name argspec body} { set result {} append result "::@args \{$argspec\} \$args" \; append result $body ::proc $name args $result } proc ::oo::define::@method {name argspec body} { set class [lindex [::info level -1] 1] set result {} append result "::@args \{$argspec\} \$args" \; append result $body oo::define $class method $name args $result } ====== And here are some examples of play testing the new rules: ====== proc standard {subject sender {args { mtime {mandatory 0} body {} }}} { set auto_reply [subst {To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } puts "STANDARD" puts [info args standard] puts [info body standard] puts -- puts [standard {Hi there} {yoda@etoyoc.com} body {Extra garbage}] ===== Output: ===== STANDARD subject sender args ::@args { mtime {mandatory 0} body {} } $args; set auto_reply [subst {To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply -- To: yoda@etoyoc.com Subject: Re: Hi there Dear yoda@etoyoc.com, Thank you for writing us about Hi there ===== New proc style ===== @proc newstyle { subject {mandatory 1} sender {mandatory 1} mtime {mandatory 0} body {} } { set auto_reply [subst {To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } puts "NEW" puts [info args newstyle] puts [info body newstyle] puts -- puts [newstyle subject {Hi there} sender {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]] ===== Output: ===== NEW args ::@args { subject {mandatory 1} sender {mandatory 1} mtime {mandatory 0} body {} } $args; set auto_reply [subst {To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply -- To: yoda@etoyoc.com Subject: Re: Hi there Dear yoda@etoyoc.com, Thank you for writing us about Hi there on Wed Oct 25 11:46:00 EDT 2017 ===== As an OO method ===== proc ::UuidNext {} { global NextUuid return [incr NextUuid] } oo::class create nclass { method omessage args { dict with args {} if {![dict exists $args uuid]} { set uuid [::UuidNext] } set auto_reply [subst {Msgid: $uuid To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } @method message { subject {mandatory 1} sender {mandatory 1 aliases from} mtime {mandatory 0} body {} uuid {mandatory 0} } { if {![dict exists $args uuid]} { set uuid [::UuidNext] } set auto_reply [subst {Msgid: $uuid To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } } puts "OO METHOD" puts [info class definition ::nclass message] puts -- nclass create N puts [N message subject {Hi there} from {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]] ====== And the output: ====== OO METHOD args {::@args { subject {mandatory 1} sender {mandatory 1 aliases from} mtime {mandatory 0} body {} uuid {mandatory 0} } $args; if {![dict exists $args uuid]} { set uuid [::UuidNext] } set auto_reply [subst {Msgid: $uuid To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } -- Msgid: 1 To: yoda@etoyoc.com Subject: Re: Hi there Dear yoda@etoyoc.com, Thank you for writing us about Hi there on Wed Oct 25 11:46:00 EDT 2017 ====== Performance Using the following script, I've run performance benchmarks on both the pure-tcl and C extension implementations: ====== puts "Raw unmodifed proc:" puts [time {unmodified {Hi there} {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]} 1000] puts "New Args style proc:" puts [time {standard {Hi there} {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]} 1000] puts "New @proc defined parameters:" puts [time {newstyle subject {Hi there} sender {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]} 1000] puts "Raw method with args:" puts [time {N omessage subject {Hi there} sender {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]} 1000] puts "New @method defined parameters:" puts [time {N message subject {Hi there} from {yoda@etoyoc.com} body {Extra garbage} mtime [clock format [clock seconds]]} 1000] ====== The Pure Tcl implementation scores thus: ====== Raw unmodifed proc: 33.248723 microseconds per iteration New Args style proc: 36.088394 microseconds per iteration New @proc defined parameters: 44.550999000000004 microseconds per iteration Raw method with args: 32.744488000000004 microseconds per iteration New @method defined parameters: 47.666799 microseconds per iteration ====== The C implementation scores thus: ====== Raw unmodifed proc: 33.116153 microseconds per iteration New Args style proc: 30.772014 microseconds per iteration New @proc defined parameters: 35.272524 microseconds per iteration Raw method with args: 32.589664 microseconds per iteration New @method defined parameters: 34.468402999999995 microseconds per iteration ====== The "Raw unmodified" metric is a proc build with the native Tcl proc command: ====== _proc unmodified {subject sender args} { dict with args {} set auto_reply [subst {To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } ====== The Raw method metric is a method defined by the native oo::method mechanism: ===== method omessage args { dict with args {} if {![dict exists $args uuid]} { set uuid [::UuidNext] } set auto_reply [subst {Msgid: $uuid To: $sender Subject: Re: $subject Dear $sender, Thank you for writing us about $subject}] if {[dict exists $args mtime]} { append auto_reply " on [clock format [clock scan $mtime]]" } return $auto_reply } ===== <>Enter Category Here