From: Twylite <tw...@cr...> - 2008-05-09 14:43:25
|
Hi, > proc myupvar {level varName local} { > upvar [expr {$level+1}] $varName var > if {![info exists var]} { return -code error "no such variable > \"$varName\"" } > uplevel 1 [list upvar $level $varName $local] > } Yes, that would be upvar-with-guarantee-that-variable-exists. > Combine this with the wiki code for proc foo {&bar} ... and you seem > to have all of the advantages of any special syntax. I assume you're talking about Implicit upvar (http://wiki.tcl.tk/4535). No - you're still missing one thing: with implicit upvar the proc controls the semantics (pass-by-value or pass-by-reference); with $& syntax the caller is in control. > Note that the existing behaviour of [upvar] does have its uses, > however -- e.g. it is possible to create constructs that *create* > variables in the caller's scope with it. That is not possible with $&. Not even vaguely disputed ;) >>> proc add10 var { incr var 10 } >>> set foo 1 >>> add10 $foo ;# does nothing at all - no error > That wasn't the intention though -- it is intended to be passed a var > and mutate it by incrementing it by 10. i.e., the correct code should > have been: > > add10 $&foo > > My point is that the broken code I showed doesn't even give an error > -- a clear disadvantage in comparison to upvar. It simply does > nothing. This can only lead to confusion. No more or less confusing that using $d (value) when you meant d (varname), or any other misreading of an API. "add10 $foo" will return 10 and not adjust foo, much like "lappend $a b c" doesn't complain and doesn't adjust a. Any proc can modify the values of its parameter variable. Those modifications are lost when the proc returns. $& syntax provides a way to keep those values (in the caller's context). Upvar also allows a way to keep those values, but the proc must be written to use either a varname (+ upvar) or a value. $& allows the caller to capture the changes values _if desired_. > Then use [linsert] instead of [lappend]: *THWAP* Yes, Tcl offers other ways to accomplish my trivial example. But IF Tcl had $& support, then lappend COULD HAVE been implemented as "lappend listvalue ?value value ...?", allowing you to use it in a mode with or without side-effects. In the same way incr COULD HAVE been implemented as "incr value ?increment?" allowing it to work as it currently does OR as a shortcut for [expr { $value + 1 }] (no side-effects) >> But if lappend had been written to use references: >> set b alpha -> alpha >> set c [lappend $&b beta] -> alpha beta >> puts $b -> alpha >> puts $c -> alpha beta > That doesn't follow at all from your description of $&-syntax. Indeed, > I would expect the result of this to be identical to the previous > version. What you want here is pass-by-value semantics, so introducing > a syntax for pass-by-reference is no help at all. You're absolutely right, it doesn't follow. That's because I didn't have a Tcl interp with $& to test my example ;) Let me try that again: The idea is that you can rewrite lappend to use pass-by-value (in a hypothetical "$& existed in the past" scenario - I'm not suggesting we rewrite lappend): lappend listvalue ?value value ...? Then set b alpha -> alpha set c [lappend $b beta] -> alpha beta # currently [lappend $b beta] would set the value of "alpha" to "beta" return "beta" puts "$b | $c" -> alpha | alpha beta puts $alpha -> can't read "alpha": no such variable ;# just for clarity lappend $&b gamma -> alpha gamma puts "$b | $c" -> alpha gamma | alpha beta So what if you DID want to set the value of "alpha" to "beta"? set b alpha -> alpha set c [lappend $&{$b} beta] -> alpha beta or perhaps set c [lappend $&[set b] beta] -> alpha beta So there interesting question is, what does "set d $&b" do? According to my explanation it would be the same as "set d $b", but Fr?d?ric may disagree: it could be d a variable containing a reference to b, so that you could [lappend $d beta] and affect b (effectively [lappend $&b beta]). That could get really ... dodgy ;) It depends on whether you make a reference a new var type (with special syntax support) or just a particular way of passing information on the stack. Trevor |