# TIP 229: Scripted Control of Name Resolution in Namespaces
	State:		Final
	Type:		Project
	Tcl-Version:	8.5
	Vote:		Done
	Post-History:	
	Author:		Donal K. Fellows <donal.k.fellows@man.ac.uk>
	Created:	03-Nov-2004
	Tcl-Ticket:	1159942
-----

# Abstract

This TIP proposes extensions to the **namespace** command to allow
scripts to control how individual namespaces map names to commands.

# 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 **upvar** or
**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\).

# Proposed Change

## Namespace Path Subcommand

The **namespace** command will gain a new subcommand, **path**,
with the following syntax:

 > **namespace path** ?_list_?

This command sets and queries the current namespace's command name
resolution path. If _list_ is present, **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
_list_ argument is provided, **namespace path** doesn't change
anything and returns the current path.

## Updates to Other Commands

The **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 **info procs** command will not be so modified.

## 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
**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 **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.

## Examples

The following script returns "::foo":

	namespace eval ::foo {
	   proc boo {} {namespace current}
	   namespace eval bar {
	      namespace path ::foo
	      boo
	   }
	}

The following script return "::foo::bar":

	namespace eval ::foo {
	   proc boo {} {namespace current}
	   namespace eval bar {
	      proc boo {} {namespace current}
	   }
	   namesspace eval spong {
	      namespace path ::foo
	      bar::boo
	   }
	}

# Implementation

A patch is available<http://sf.net/tracker/?func=detail&aid=1159942&group_id=10894&atid=310894> .

# Copyright

This document has been placed in the public domain.

