First, there is the ability to wrap an existing command:
% proc foo {} {puts foo}
% rename foo _foo
% proc bar {noise} {puts "bar $noise"; _foo}
% interp alias {} foo {} bar alias
foo
% foo
bar alias
foo
Second, there is the ability to use interpreter aliases just like they
were Tcl commands.
% proc base {} {puts base}
% interp alias {} foo {} base
foo
% foo
base
BUT, if you try to wrap an alias, it fails:
% proc base {} {puts base}
% interp alias {} foo {} base
foo
% rename foo _foo
% proc bar {noise} {puts "bar $noise"; _foo}
% interp alias {} foo {} bar alias
foo
% foo
bar alias
invalid command name "_foo"
What's going on? Is this expected? Is it a bug? Can it be fixed so
that aliases are not distinguishable from procs in this way?
Why do I care? I use the wrapping technique to wrap [exit] so I can
call exit handlers. This works great in my master interpreter. When I
create a slave, I want [exit] in the slave to be an interpreter alias
which only destroys the slave, not the whole app. But then the exit
handler mechanism fails in the slave.
--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|
I would call this a bug, and definitely unexpected. The interp docs
don't specifically say this should work as above, and the above is
definitely not intuitive. I know that when the command was developed,
some things weren't done to prevent loop conditions, but I think the
above should work. The _foo does work directly after the rename.
--
Jeffrey Hobbs The Tcl Guy
hobbs at ajubasolutions.com Ajuba Solutions (née Scriptics)
I was curious how far back this behavior went. [interp] arrived in
Tcl 7.5 and...
% info patchlevel
7.5p1
% proc base {} {puts base}
% interp alias {} foo {} base
foo
% rename foo _foo
% proc bar {noise} {puts "bar $noise"; _foo}
% interp alias {} foo {} bar alias
Segmentation fault
Tcl 7.6 fixed the segfault, and introduced the current behavior.
Jeffrey Hobbs <jeffre...@ajubasolutions.com> wrote:
> I would call this a bug, and definitely unexpected.
--
| Don Porter dgpo...@erols.com |
| "Some days you just can't get rid of a bomb!" |
| -- Adam West as BATMAN |
|______________________________________________________________________|
After very carefully reading interp(n) and examining tests interp-19.*
in the test suite, it seems this is the intended behavior. Although an
alias can be [rename]d, the [interp alias] command still accesses the
alias by the name with which the alias was created:
% interp alias {} foo {} list
foo
% interp aliases
foo
% rename foo _foo
% interp aliases
foo
Apparently this is so the creator of an alias can destroy that alias
without having to track [rename]s of the alias.
Having [interp alias] return a token for this purpose, like [after],
would probably have been a better idea, but things are as they are.
So, my wrapping technique now needs to guard against aliases, since
they are different in this way:
% proc base {} {puts base}
% interp alias {} foo {} base
foo
% rename foo _foo
% proc bar {noise} {puts "bar $noise"; _foo}
% if {[lsearch [interp aliases] foo] == -1} {
interp alias {} foo {} bar alias
} else {
proc foo args {eval bar alias $args}
}
% foo
bar alias
base