ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> tcl-core
tcl-core
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

Privacy Policy | Email Opt-out | Feedback | Syndication
© 2004 ActiveState, a division of Sophos All rights reserved