Tcl Source Code

View Ticket
Login
Ticket UUID: 559268
Title: incorrect [namespace forget] docs
Type: Bug Version: obsolete: 8.4a5
Submitter: dgp Created on: 2002-05-22 16:44:48
Subsystem: 21. [namespace] Assigned To: msofer
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2002-06-04 00:05:18
Resolution: Fixed Closed By: msofer
    Closed on: 2002-06-03 17:05:18
Description:
The documentation of

namespace forget ?pattern ...?

claims that each "pattern" must be a qualified
name.  That is, it must contain a "::".  It further
claims that everything to the left of the rightmost
"::" must be a literal name of an exporting namespace,
while everything to the right of it can be a pattern
for matching against exported commands of that
namespace.

In fact, simple names are permitted as arguments
to [namespace forget] and that can be quite
useful.

  namespace eval importer {
namespace import ::exporter::foo
namespace forget foo
  }

will work fine to undo the import.  In this example,
it would be just as easy to explicitly repeat

namespace forget ::exporter::foo

but consider the case where the exporting namespace
is actually an argument passed into a proc, and 
the [namespace forget] comes at a later time.  It
would be a real pain to have to store which exporting
namespace the command was imported from, just so you
could successfully [namespace forget] it later.

(Hmmm... I guess it's not so bad, becuase

namespace forget [namespace origin foo]

should always work, but why the extra scoping if
it's not really necessary?)

Anyhow, the simple case does work, so that
should be documented.

It appears it will even work with a [rename]d
imported command:

namespace eval importer {
    namespace import ::exporter::foo
    rename foo bar
    namespace forget bar
}

Someone more familiar with the internals of 
[namespace] than I am should update the docs, so
the exact requirements and capabilities can be
documented correctly.
User Comments: msofer added on 2002-05-25 03:20:42:
Logged In: YES 
user_id=148712

The funny behaviour of [namespace forget] is the subject of
[Bug #560297]; this ticket here concerns only the
undocumented behaviour for simple names.

msofer added on 2002-05-25 02:59:45:

File Added - 23696: NSforget.diff

Logged In: YES 
user_id=148712

Attaching a patch to the docs.

msofer added on 2002-05-23 05:14:48:
Logged In: YES 
user_id=148712

RFC: Should I document the current behaviour, or rather
adapt behaviour to the docs? Or both?

The current behaviour is:

1. If the cmd name (or pattern)  is qualified, check for
existence of a corresponding command in the NS given by the
qualifier, and remove same-named commands in the local
namespace if they are imported commands (even if imported
from somewhere else, see example below)

2. If the cmd name (or pattern) is simple, remove the
corresponding commands in the local namespace if they are
imported commands

Prop.1 is (almost) the documented behaviour; Prop.2 is not
documented - but really useful. So: document and fix 1?

Prop.1 looks buggy and dangerous to me (as implemented): you
can 'forget' a command imported from somewhere else! Example:

% namespace eval src0 {proc a {} {puts 0}}
% namespace eval src0 {namespace export a}
% namespace eval src1 {proc a {} {puts 1}}
% namespace eval tst {namespace import ::src0::a}
% tst::a
0
% namespace eval tst {namespace forget ::src1::a}
% tst::a
invalid command name "tst::a"

msofer added on 2002-05-23 03:33:12:
Logged In: YES 
user_id=148712

Indeed, the docs are misleading. It almost seems that the
usage of unqualified names is the only safe way to
[namespace forget] an imported command, as shown in the
following:

% namespace eval tst0 {proc a {} {puts hello}}
% namespace eval tst0 {namespace export a}
%  namespace eval tst1 {namespace import ::tst0::a}
% tst1::a
hello
% namespace eval tst0 {rename a b}
% namespace eval tst1 {rename a c}
% tst1::c
hello
% # cannot forget using the original import name
% namespace eval tst1 {namespace forget ::tst0::a}
%  tst1::c
hello
% # cannot forget using the current name of the imported proc
%  namespace eval tst1 {namespace forget ::tst0::b}
% tst1::c
hello
% # cannot forget using the current local name and the
exporter's path
% namespace eval tst1 {namespace forget ::tst0::c}
%  tst1::c
hello
% # forget only using the current local name
% namespace eval tst1 {namespace forget c}
% tst1::c
invalid command name "tst1::c"

Attachments: