<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://www.tcl.tk/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Thu Jun 20 09:43:38 GMT 2013 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='276'>
<header><title>Specify and Unify Variable Linking Commands</title><author address="mailto:msofer@users.sourceforge.net">Miguel Sofer</author><status type='project' state='draft' tclversion="8.7" vote='prior'>$Revision: 1.20 $</status><history></history><created day='1' month='oct' year='2006' /><keyword>Tcl global variable upvar {namespace upvar}</keyword></header>
<abstract>The purpose of this TIP is to simplify and clarify the semantics of the commands in Tcl that couple variables in different scopes together.</abstract>
<body><section title="Rationale">
<para>This TIP proposes to specify and document the behaviour of the different variable linking commands in Tcl: <emph style="bold">global</emph>, <emph style="bold">variable</emph>, <emph style="bold">upvar</emph> and <emph style="bold">namespace upvar</emph>.</para>
<para>In particular, as many of these commands were initially designed to be mainly useful from within procedure bodies, the documentation does not specify their behaviour with respect to qualified variable names.</para>
<para>This TIP proposes to specify and document this behaviour, insuring that it is essentially the same in all these commands.</para>
<subsection title="Current Situation">
<para>There have been a few bug reports concerning the behaviour of variable linking commands with respect to qualified variable names: 604226, 1274916, 1274918. Some are real bugs, some are just surprising but correct behaviour, some are surprising unspecified behaviour.</para>
<para>Within proc bodies all of these commands create local variables that are linked to original variables elsewhere (the following assumes that <emph style="italic">local</emph> is a non-qualified name):</para>
<itemize><item.i><para>&quot;<emph style="bold">global</emph> <emph style="italic">var</emph>&quot; creates a local variable &quot;[<emph style="bold">namespace tail</emph> <emph style="italic">var</emph>]&quot; that is linked to &quot;<emph style="italic">var</emph>&quot; as resolved from the global namespace.</para></item.i><item.i><para>&quot;<emph style="bold">variable</emph> <emph style="italic">var</emph>&quot; creates a local variable &quot;[<emph style="bold">namespace tail</emph> <emph style="italic">var</emph>]&quot; that is linked to &quot;<emph style="italic">var</emph>&quot; as resolved from [<emph style="bold">namespace current</emph>].</para></item.i><item.i><para>&quot;<emph style="bold">upvar</emph> <emph style="italic">level var local</emph>&quot; creates a local variable &quot;<emph style="italic">local</emph>&quot; that is linked to &quot;<emph style="italic">var</emph>&quot; as resolved in the context of the frame identified by <emph style="italic">level</emph>. It is an error to try to link to a proc-local variable from a namespace context. It is an error to link a variable to itself.</para></item.i><item.i><para>&quot;<emph style="bold">namespace upvar</emph> <emph style="italic">ns var local</emph>&quot; creates a local variable &quot;<emph style="italic">local</emph>&quot; that is linked to &quot;<emph style="italic">var</emph>&quot; as resolved from namespace <emph style="italic">ns</emph> (itself resolved in the current context). It is an error to link a variable to itself.</para></item.i></itemize>
<para>One undocumented issue is what should happen when <emph style="italic">local</emph> is a qualified name.</para>
<para>Another issue is the behaviour of these commands when invoked outside of procedure bodies:</para>
<itemize><item.i><para>&quot;<emph style="bold">global</emph> <emph style="italic">var</emph>&quot; is documented to be a no-op.</para></item.i><item.i><para>&quot;<emph style="bold">variable</emph> <emph style="italic">var</emph>&quot; is documented to create a namespace variable in the current namespace, without any mention of the behaviour when &quot;<emph style="italic">var</emph>&quot; is qualified. Currently that is a a no-op in terms of creating a variable, but it can change the value of the target, see [Bug #604226]. If <emph style="bold">var</emph> is a simple name and the corresponding variable already existed, <emph style="bold">variable</emph> may set its value (and an internal flag), but does no linking.</para></item.i><item.i><para>&quot;<emph style="bold">upvar</emph> <emph style="italic">level var local</emph>&quot; creates a variable &quot;<emph style="italic">local</emph>&quot; (as resolved from [<emph style="bold">namespace current</emph>]) that is linked to &quot;<emph style="italic">var</emph>&quot; as resolved in the context of the frame identified by <emph style="italic">level</emph>. It is an error to try to link to a proc-local variable from a namespace context. It is an error to link a variable to itself.</para></item.i><item.i><para>&quot;<emph style="bold">namespace upvar</emph> <emph style="italic">ns var local</emph> creates a variable &quot;<emph style="italic">local</emph>&quot; (as resolved from [<emph style="bold">namespace current</emph>]) that is linked to &quot;<emph style="italic">var</emph>&quot; as resolved from namespace <emph style="italic">ns</emph> (itself resolved in the current context). It is an error to link a variable to itself.</para></item.i></itemize>
</subsection>
</section>
<section title="Proposal">
<para>This TIP proposes to unify the criteria, making all of these commands essentially implementable in Tcl from the most general, <emph style="bold">upvar</emph>. The behaviour should <emph style="italic">not</emph> depend on the commands being invoked within or outside of a procedure body.</para>
<para>In all of the following, it is an error for <emph style="italic">local</emph> to be a qualified variable name.</para>
<itemize><item.i><para>&quot;<emph style="bold">global</emph> <emph style="italic">var</emph>&quot; always creates a variable &quot;[<emph style="bold">namespace tail</emph> <emph style="italic">var</emph>]&quot; in the current context, linked to a global variable &quot;<emph style="italic">var</emph>&quot;.</para></item.i><item.i><para>&quot;<emph style="bold">variable</emph> <emph style="italic">var</emph>&quot; always creates a variable &quot;[<emph style="bold">namespace tail</emph> <emph style="italic">var</emph>]&quot; in the current context, linked to a variable &quot;<emph style="italic">var</emph>&quot; as resolved from [<emph style="bold">namespace current</emph>].</para></item.i><item.i><para>&quot;<emph style="bold">upvar</emph> <emph style="italic">level var local</emph>&quot; always creates a variable &quot;<emph style="italic">local</emph>&quot; in the current context, linked to &quot;<emph style="italic">var</emph>&quot; as resolved in the context of the frame identified by <emph style="italic">level</emph>. It is an error to try to link to a proc-local variable from a namespace context.</para></item.i><item.i><para>&quot;<emph style="bold">namespace upvar</emph> <emph style="italic">ns var local</emph>&quot; always creates a variable &quot;<emph style="italic">local</emph>&quot; in the current context, linked to &quot;<emph style="italic">var</emph>&quot; as resolved from namespace <emph style="italic">ns</emph> (itself resolved in the current context).</para></item.i></itemize>
<para>In all cases, attempting to link a variable to itself will be a no-op.</para>
</section>
<section title="Compatibility">
<para>This TIP may cause breakage in some scripts relying on undocumented behaviour.</para>
<para>The specification changes for <emph style="bold">global</emph> and <emph style="bold">variable</emph> outside of proc bodies is almost certainly implementing what the programmer meant them to do, hence likely to fix more bugs than it causes. </para>
</section>
<section title="Reference Implementation and Documentation">
<para>Forthcoming at SF.</para>
</section>
<section title="Copyright">
<para>This document has been placed in the public domain.</para>
</section>
</body></TIP>
