\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#229: Scripted Control of Name Resolution in Namespaces}
\date{November 03, 2004}
\author{Donal K. Fellows}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#229}&\textbf{Scripted Control of Name Resolution in Namespaces}\\\hline
Author&

Donal K. Fellows \tipmail{donal.k.fellows}{man.ac.uk}
\\
Created&Wednesday, \(\text{3}^{\text{rd}}\) November 2004\\
Type&Project\\
Tcl Version&\(8.5\)\\
State&Final\\
Vote&Done\\
Version&\tipversion$Revision: 1.10 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP proposes extensions to the \textbf{namespace} command to allow scripts to control how individual namespaces map names to commands.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

Tcl has, for historic reasons, attracted many different styles of object system, and a favoured mechanism for implementing objects is on top of namespaces (which were introduced in Tcl 8.0 based on work done previously in [incr Tcl]). However, a common problem that these OO systems face is the inability to make namespaces efficiently map names of entities within classes etc. into the object instances. This TIP provides a simple mechanism for doing this.

No mechanism is provided for affecting the resolving of variable names. Best practice is to ensure that variables not present in the current namespace are imported explicitly through the \textbf{upvar} or \textbf{variable} commands (depending on context) and the fact that there is any possibility of non-local variable name resolution has been behind a number of bugs in the core (e.g. Bug \#981733).

\section{Proposed Change}

\subsection{Namespace Path Subcommand}

The \textbf{namespace} command will gain a new subcommand, \textbf{path}, with the following syntax:

\begin{quote}
\textbf{namespace path} ?\textit{list}?
\end{quote}

This command sets and queries the current namespace's command name resolution path. If \textit{list} is present, \textbf{namespace path} sets the path to the list of namespaces named in the list and returns the empty string; all the namespaces must exist or an error is thrown. If no \textit{list} argument is provided, \textbf{namespace path} doesn't change anything and returns the current path.

\subsection{Updates to Other Commands}

The \textbf{info commands} command shall be updated so that, when no namespace is present in its pattern part, it shall return all (matching) commands that are visible without namespace qualifiers at this point. The \textbf{info procs} command will not be so modified.

\subsection{Name Path Behaviour}

Only names without a leading namespace separator in them are resolved using the namespace's path. When resolving command names, resolving relative to the current namespace is always preferred (unless a resolver is installed, of course), and resolution relative to the global namespace is always done after resolving relative to everything in the path (unless the global namespace is explicitly in the path, when it happens earlier). This means that the old behaviour is exactly what you get when the path is empty, and also ensures that virtually all scripts continue to work when a path is set; if it was possible to remove the global namespace from the actual path (as opposed to the settable part), virtually all scripts would break. If an extension installs a custom name resolver, that completely overrides the command name resolution path mechanism (to maximize backward-compatability; it is not anticipated that much code will try to mix the two mechanisms in a namespace).

Note that each namespace's path is isolated from the path of every other namespace, including the parent namespace. Systems using the \textbf{namespace path} mechanism as part of an implementation of inheritance will want to set up the path for each object namespace explicitly (this value can be statically precomputed on a per-class basis); indeed, where multiple inheritance is involved it will probably be more efficient to compute the path than let Tcl guess.

The path is parsed completely at the time the \textbf{namespace path} command is run, and the resulting list of namespaces is used directly. If a namespace on some namespaces' path is deleted, it is immediately excised from the path of every namespace that refers to it.

\subsection{Examples}

The following script returns ``::foo'':
\begingroup\small\begin{verbatim}
namespace eval ::foo {
   proc boo {} {namespace current}
   namespace eval bar {
      namespace path ::foo
      boo
   }
}
\end{verbatim}
\endgroup

The following script return ``::foo::bar'':
\begingroup\small\begin{verbatim}
namespace eval ::foo {
   proc boo {} {namespace current}
   namespace eval bar {
      proc boo {} {namespace current}
   }
   namesspace eval spong {
      namespace path ::foo
      bar::boo
   }
}
\end{verbatim}
\endgroup

\section{Implementation}

A patch is available[\url{http://sf.net/tracker/?func=detail&aid=1159942&group_id=10894&atid=310894}].

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
