Re: [TCLCORE] Variable access (was Re: [Tcl9-cloverfield], Parser)
by Twylite other posts by this author
May 9 2008 7:43AM messages near this date
Re: [TCLCORE] Variable access (was Re: [Tcl9-cloverfield], Parser)
|
Re: [TCLCORE] Variable access (was Re: [Tcl9-cloverfield], Parser)
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
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Tcl-Core mailing list
Tcl-Core@[...].net
https://lists.sourceforge.net/lists/listinfo/tcl-core
Thread:
Twylite
Larry McVoy
Rna020
Neil Madden
Twylite
Neil Madden
Twylite
Neil Madden
|