有没有办法处理Tcl中不存在的proc?

时间:2014-03-28 11:03:40

标签: tcl

我是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来处理这些场景

4 个答案:

答案 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的名称空间,我创建了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
相关问题