我是tcl的新手。有没有办法我们可以处理虽然在脚本中被调用但不存在的过程。我给你的例子
假设这是我们的代码
package require 65ABC
package provide package1
65ABC::callingFunction param1 param2 (# this does not exist in 65ABC)
It will throw an error saying undefined command 65ABC::callingFunction
如果我记得我对TCL
的确切不确定,但在其他语言中,在这些情况下会有universal proc
。这意味着在上面提到的场景中,当调用函数不存在时,它将进入一些通用过程,并执行在通用过程中编写的内容。假设我们可以打印一条消息,说“此proc不存在”,或者我们可以进行其他操作。
更新:添加catch
命令不是一个选项。因为我大概有200个这样的过程。我想通过一个superproc来处理这些场景
答案 0 :(得分:7)
您要查找的是unknown
和/或namespace unknown
命令。这些命令记录在这里:
以下是unknown
的简短示例:
% rename unknown _unknown ;# save reference to the original
% proc unknown {args} {
puts stderr "Hey, I don't know this command: $args"
uplevel 1 [list _unknown {*}$args]
}
% hello world
Hey, I don't know this command: hello world
invalid command name "hello"
当然,您可以在此过程中执行任何操作 - 您可以记录信息,动态创建缺失过程,引发错误等等。
答案 1 :(得分:1)
您可以使用catch
:
package require 65ABC
package provide package1
if {[catch {65ABC::callingFunction param1 param2} err]} {
puts "Error: $err"
}
或者try
...... on error
:
package require 65ABC
package provide package1
try {
65ABC::callingFunction param1 param2
} on error {result options} {
puts "Something's not so right..."
return -options $options $result
}
答案 2 :(得分:1)
原始海报(OP)似乎对处理名称空间65ABC
中的未知程序感兴趣。如果是这种情况,则proc unknown
必须更具选择性:它必须确定未知proc所属的名称空间。如果是65ABC
,那么我们将自己处理。否则,我们将让系统处理它。以下是我的想法:
rename unknown original_unknown; # Save the original unknown
proc getns {name {defaultNS "::"}} {
set lastSeparatorPosition [string last "::" $name]
if {$lastSeparatorPosition == -1} {
return $defaultNS
} else {
incr lastSeparatorPosition -1
return [string range $name 0 $lastSeparatorPosition]
}
}
proc unknown {args} {
set procName [lindex $args 0]
set ns [getns $procName]
puts "$args, happens in name space -- $ns"
if {$ns == "::65ABC" || $ns == "65ABC"} {
puts " We will handle this ourselves"
} else {
uplevel 1 [list original_unknown {*}$args]
}
}
# Test it out
namespace eval ::65ABC {
proc foo {args} { puts "::65ABC::foo $args" }
# This will never get called
proc unknown {args} {
puts "::65ABC::unknown -- $args"
}
}
::65ABC::bar hello there; # We will handle this case
65ABC::foobar 1 2 3; # Also handle this case
foo bar; # The system will handle this case
::65ABC::bar hello there, happens in name space -- ::65ABC
We will handle this ourselves
65ABC::foobar 1 2 3, happens in name space -- 65ABC
We will handle this ourselves
foo bar, happens in name space -- ::
invalid command name "foo"
while executing
"original_unknown foo bar"
("uplevel" body line 1)
invoked from within
"uplevel 1 [list original_unknown {*}$args]"
(procedure "::unknown" line 12)
invoked from within
"foo bar"
(file "/Users/haiv/Dropbox/src/tcl/unknown_proc.tcl" line 47)
proc unknown
基本上与Bryan Oakley相同,但有一些额外的代码来确定未知proc所属的名称空间。proc gents
,它返回最后"::"
之前的文本。如果proc名称不包含"::"
,则gents
将返回全局名称空间的"::"
。unknown
中编写65ABC
proc不起作用。我试过了。答案 3 :(得分:0)
这只是Bryan Oakley回答的扩展。您可以使用tcl的内省来查看调用者并采取适当的操作。任何不是源自B ::名称空间的调用都将照常处理。
rename unknown _unknown
proc unknown {args} {
array set i [info frame 1]
# if the uknown command is in the B:: namespace, use our own
# handler, otherwise, run the default.
if { [regexp {^B::} $i(cmd)] } {
puts "unk: $args"
} else {
uplevel 1 [list _unknown {*}$args]
}
}
namespace eval B {
proc x {} {
puts "B::x"
}
}
B::x
B::y
xyzzy