Google 網路論壇不再支援新的 Usenet 貼文或訂閱項目,但過往內容仍可供查看。

[rename] alias GOTCHA!

瀏覽次數:5 次
跳到第一則未讀訊息

Don Porter

未讀,
2000年8月3日 凌晨3:00:002000/8/3
收件者:
Two neat features of Tcl yield a surprising result when combined.

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 |
|______________________________________________________________________|

Jeffrey Hobbs

未讀,
2000年8月3日 凌晨3:00:002000/8/3
收件者:d...@cam.nist.gov

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)

Don Porter

未讀,
2000年8月3日 凌晨3:00:002000/8/3
收件者:
Don Porter wrote:
>> 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"

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 |
|______________________________________________________________________|

Don Porter

未讀,
2000年8月4日 凌晨3:00:002000/8/4
收件者:
Don Porter <d...@cam.nist.gov> wrote:
> 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?

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

0 則新訊息