如何在tcl提示符中抑制proc的返回值

时间:2013-04-01 11:44:37

标签: tcl return-value

我在TCL中比较新,在TCL提示符下,当我们调用带有一些返回值的proc时,proc的返回值由tcl回显。有没有办法阻止它(不影响看跌期权或类似功能)作为例子

bash$ tclsh
% proc a {} { puts  "hello"; return 34; }
% a
hello
34
%

现在我如何抑制34进入屏幕?任何帮助表示赞赏。

更新: 实际上proc是另一个工具的一部分,之前它没有任何返回值,但现在有条件地它可以返回一个值。 它可以从脚本中调用,不会有任何问题(正如布莱恩指出的那样)。它可以从交互式提示中调用,然后在所有必要的输出之后,返回值被不必要地打印出来。 所以1)我没有改变用户的tclshrc的工具2)现有的脚本应该继续工作。 并且看起来奇怪的是每次调用proc时,在所有必要的输出之后,都会打印一个数字。对于用户来说,这是一个不必要的信息,除非他已经抓住了价值并想要做某事。所以我希望将价值交付给用户,但不要打印到提示/ UI(希望我很清楚)

3 个答案:

答案 0 :(得分:2)

tclshwish中的交互式shell代码将打印任何非空结果。为了不打印任何内容,您必须让“line”上的最后一个命令产生一个空结果。但是使用哪个命令?

许多命令会产生空结果:

if 1 {}
subst ""
format ""

然而,最短的可能是:

list

因此,您可以编写代码,如:

a;list

当然,只有当您的命令实际产生一个您不想看到的大结果时,这才真正有用。在这些情况下,我经常发现使用衡量结果大小的东西是最有用的,例如:

set tmp [something_which_produces a_gigantic result]; string length $tmp

我找到的最有用的命令是string lengthllengthdict size


如果绝对必须不打印命令的结果,则必须编写自己的交互式循环。有两种方法可以执行此操作,具体取决于您是否在事件循环内运行:

没有事件循环

这个简单的版本只是检查命令名是否在用户键入的内容中。否则,任意抛弃结果可能不是一个好主意!

set accum ""
while {[gets stdin line] >= 0} {
    append accum $line "\n"
    if {[info complete $accum]} {
        if {[catch $accum msg]} {
            puts stderr $msg
        } elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
            puts $msg
        }
        set accum ""
    }
}

使用事件循环

这只是处理阻塞IO的情况;当输入来自熟食终端时(即默认值),这是正确的事情

fileevent stdin readable handleInput
set accum ""
proc handleInput {} {
    global accum
    if {[gets stdin line] < 0} {
        exit; # Or whatever
    }
    append accum $line "\n"
    if {[info complete $accum]} {
        if {[catch {uplevel "#0" $accum} msg]} {
            puts stderr $msg
        } elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
            puts $msg
        }
        set accum ""
    }
}
vwait forever; # Assuming you're not in wish or have some other event loop...

如何检测正在执行的命令

上面的代码使用![string match *TheSpecialCommand* $accum]来决定是否丢弃命令结果,但这非常难看。利用Tcl自带的内置钩子的更优雅的方法是使用execution trace来检测命令是否已被调用(为简洁起见,我将在此处仅显示非事件循环版本)。这样做的另一个好处是可以很容易地扩展以抑制多个命令的输出:只需将跟踪添加到每个命令。

trace add execution TheSpecialCommand enter SuppressOutput
proc SuppressOutput args {
    # Important; do not suppress when it is called inside another command
    if {[info level] == 1} {
        set ::SuppressTheOutput 1
    }
}

# Mostly very similar from here on
set accum ""
while {[gets stdin line] >= 0} {
    append accum $line "\n"
    if {[info complete $accum]} {
        set SuppressTheOutput 0;                       # <<<<<< Note this!
        if {[catch $accum msg]} {
            puts stderr $msg
        } elseif {$msg ne "" && !$SuppressTheOutput} { # <<<<<< Note this!
            puts $msg
        }
        set accum ""
    }
}

要清楚,我不会永远在我自己的代码中执行此操作!如果重要的话,我只是手动抑制输出。

答案 1 :(得分:1)

您可以在.tclshrc ...

中创建一个空过程
proc void {} {}

...当您不需要返回值时,请使用;void结束该行。

答案 2 :(得分:-1)

使用 tcl_interactive 变量来启用值的返回,虽然我不确定这在哪里有用...

proc a {} {
    puts "hello"
    if { [info exist tcl_interactive] } {
        return {};
    } else {
        return 34;
    }
}