Posted to tcl by sebres at Wed Mar 11 20:29:54 GMT 2020view raw
- # My thoughts trying to explain the concerns around proposed tcl-parser syntax enhancement for better
- # get-default or a catch fallback with default value (as gracefully return), as opposite to
- # TIP #323 (Do Nothing Gracefully), or rather to extend or improve it (by "compatible" syntax modification).
- # Here is my variant:
- if {[dict get $d $k {:}""] ne ""} { ... }
- # related dgp's opposite (by the objection "No language level change is needed to make this possible."):
- if {[? {dict get $d $k} : ""] ne ""} { ... }
- # As already said the variant with command would be really similar to the "catch", so
- # indirectly it would "protect" against failures of whole script {dict get $d $k},
- # whereas my variant is affecting evaluation of "dict get" only (without to involve the substitution),
- # so it could still fail if $d or $k are not resolvable as a variables...
- # from this point of view it is more "precise" applicable.
- # As for the performance, here is the simple implementation of Don's "proposal" without a language level change:
- proc ? {command args} {
- if {[llength $args] > 2 || [lindex $args 0] ne ":"} {
- return -code "wrong # args: should be \"? command ??:? fallback-value?\""
- }
- if {[info exists ::errorInfo]} { set ei $::errorInfo }
- if {[info exists ::errorCode]} { set ec $::errorCode }
- if {![catch {uplevel $command} v]} {
- return $v
- }
- if {[info exists ei]} { set ::errorInfo $ei } else { unset -nocomplain ::errorInfo }
- if {[info exists ec]} { set ::errorCode $ec } else { unset -nocomplain ::errorCode }
- return [lindex $args end]
- }
- # results (tested with core 8.6th and my fork (see below why), but shows almost the same impact in both):
- # -- positive case (v exists) --
- % proc test {} { set v "existing"; timerate { ? {set v} : default } }; test
- 2.293243 µs/# 426820 # 436063 #/sec 978.802 net-ms
- # -- negative case (no variable) --
- % proc test {} { timerate { ? {set v} : default } }; test
- 8.440286 µs/# 117787 # 118479 #/sec 994.156 net-ms
- # And comparison to enhancement proposal of me (executed in my fork, where I have
- # a pre-processor that is able to "compile" this to a TEBC with better beginCatch(safe)/endCatch
- # instructions, that I use to avoid stack traversing and error handling for blocks marked as "safe"):
- # -- positive case (v exists) --
- % proc test {} { set v "existing"; timerate { . v {:}default } }; test
- 0.011914 µs/# 24569018 # 83932653 #/sec 292.723 net-ms
- # -- negative case (no variable) --
- % proc test {} { timerate { . v {:}default } }; test
- 0.030033 µs/# 12547012 # 33297185 #/sec 376.819 net-ms
- # That shows almost 200x performance impact by implementation without "language level change".
- # and I suppose the fallback (negative) case can be still optimized to the same performance as positive,
- # if on the fly error generation (here for message "can't read "v": no such variable") would be avoided
- # by some new interpreter flag or if TEBCResume would get some common additional branch for a fallback result,
- # so I guess I could reach 0.014 - 0.015 µs/# in negative case (what would make > 600x difference to command "?").
- # There are basically the same pros for the syntax enhancement as they were provided at the point
- # where expansion via {*} (compared to expand commands) gets discussed and implemented.