From: Don H. <du...@gm...> - 2016-12-10 22:01:14
|
> With the proposed scheme, you're still passing a variable name to the > procedure... You're doing the exact same thing on the caller side. > What is "variable itself" ? Isn't the "variable name" that defines the > "variable itself"? I thought variables are defined by their name, and > nothing else. So if that's counter-intuitive and can be confusing, > then the proposed scheme is also counter-intuitive and can be > confusing (you're still passing a variable name from the caller). The variable name wasn't the point. When you do: proc foo {*varRef} {set varRef bar} foo var ref is a reference to the variable 'var', in that, you effectively operate on that same variable. There is no hoops to jump through. Maybe I'm in the minority or simply not as used to it, but I find it more clear than having to explicitly perform a variable lookup and create a new variable to link it to via [upvar]. As I'm trying to teach newbies how to use Tcl, most of them find it confusing that [upvar] needs a new variable name for the link, when that isn't required for 'global' and 'variable'. > "It is an error for a link to have a default value because it doesn't > make semantic sense (i.e., /proc foo {{*a bar}}" > > Why doesn't it make sense? I don't have an issue with it and will remove that constraint (soon, unless there are objections). When it was designed, I was thinking that the caller should be responsible for providing the variable names. I didn't see a reasonable use case for allowing defaults for this purpose. The design and TIP is still a WIP. I value all feedback and appreciate everyone's time discussing this. On 12/10/2016 6:57 AM, Peter S wrote: > 1. Is this really worth it? Is the performance benefit so large? There are evidently users taking a DIY approach. Each with their own implementations, subtle differences, and bugs. That is all fine and well, but when that is happening I believe such facilities (when practical) should become a candidate for inclusion in the language itself. For performance, on one system: Over [upvar], there is a 66% improvement. Over [upvar 1] there is a 18% improvement. As usual with benchmarks, YMMV. On a VM the #s were all over the place and far different on most runs. This benchmark was performed on a non-busy non-VM system where each run gave me consistent results. # doNoLinking - No linking done 757158 microseconds per iteration # doUpvarAlt - The upvar alternative, notice it is faster than the doNoLinking proc. 726057 microseconds per iteration # doUpvar 1455116 microseconds per iteration # doUpvar2 1209665 microseconds per iteration # doUpvar3 863843 microseconds per iteration proc doNoLinking {a b} { set a bar set b baz } proc doUpvarAlt {*a *b} { set a bar set b baz } proc doUpvar {a b} { upvar $a la upvar $b lb set la bar set lb baz } proc doUpvar2 {a b} { upvar $a la $b lb set la bar set lb baz } proc doUpvar3 {a b} { upvar 1 $a la $b lb set la bar set lb baz } proc bench {} { # Warmup the caches first set c {} set d {} for {set i 0} {$i < 100000} {incr i} { doUpvar c d } puts [time { for {set i 0} {$i < 1000000} {incr i} { doNoLinking a b } }] set a {} set b {} puts [time { for {set i 0} {$i < 1000000} {incr i} { doUpvarAlt a b } }] puts [time { for {set i 0} {$i < 1000000} {incr i} { doUpvar c d } }] puts [time { for {set i 0} {$i < 1000000} {incr i} { doUpvar2 c d } }] puts [time { for {set i 0} {$i < 1000000} {incr i} { doUpvar3 c d } }] } bench |