如何从-command选项中的代码获取结果

时间:2018-06-05 02:06:53

标签: tcl tk

参考:https://en.wikibooks.org/wiki/Tcl_Programming/Tk_examples#A_little_calculator

我是初学者Tcl语言。 我将尝试使用此计算器代码进行因子程序,

使用按钮“!”

发生了这样的错误:

invalid command name "if{x<2}"
invalid command name "if{x<2}"
    while executing
"if{x<2} {
 return 1
} else "
    (procedure "fac" line 2)
    invoked from within
"fac {$row}"
    invoked from within
".20 invoke"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 [list $w invoke]"
    (procedure "tk::ButtonUp" line 24)
    invoked from within
"tk::ButtonUp .20"
    (command bound to event)

并使用“!”在这样的键盘错误代码

    wrong # args: should be "fac x"
    wrong # args: should be "fac x"
        while executing
    "fac"
        (command bound to event)

在此代码中

package require Tk
    wm title . Calculator
    grid [entry .e -textvar e -just right] -columnspan 5
    bind .e <Return> =
    bind .e <!> fac

    set n 0

    foreach row {
       {7 8 9 + -}
       {4 5 6 * /}
       {1 2 3 ( )}
       {C 0 . = !}
    } {
       foreach key $row { 
           switch -- $key {
               =       {set cmd =}
               C       {set cmd {set clear 1; set e ""}}
               !       {set cmd {[fac {$row}]}} 
               default {set cmd "hit $key"}
           }
           lappend keys [button .[incr n] -text $key -command $cmd]
       }
       eval grid $keys -sticky we ;#-padx 1 -pady 1
       set keys [list]
    }
    grid .$n -columnspan 2 ;# make last key (=) double wide
    proc = {} {
       regsub { =.+!} $::e "" ::e ;# maybe clear previous result
       if [catch {set ::res [expr [string map {/ *1.0/} $::e]]}] {
           .e config -fg red 
       }
       append ::e = $::res 
       .e xview end
       set ::clear 1
    }
    proc fac {x} {
    if{$x<2} {
     return 1
    } else 
    {
    return $x[fac[incr x-1]]
    }
    }

    # expr {$x<2? x 1: $x*[fac [incr x -1]]}}

    proc hit {key} {
       if $::clear {
           set ::e ""
           if ![regexp {[0-9().]} $key] {set ::e $::res}
           .e config -fg black
           .e icursor end
           set ::clear 0
       }
       .e insert end $key
    }
    set clear 0
    focus .e           ;# allow keyboard input
    wm resizable . 0 0

所以,我无法在-command或cmd获得结果过程。

如何使用Tcl中的cmd,-command选项获取返回过程结果?

很抱歉难以阅读英文,谢谢。

P.S。我想“cmd”,在“宏”中是否可能是其他语言(如C风格)?

1 个答案:

答案 0 :(得分:0)

你的问题是:

proc fac {x} {
if{$x<2} {
 return 1
} else 
{
return $x[fac[incr x-1]]
}
}

不计算阶乘。是的,它声明了一个过程fac,但过程的实现脚本在多种方面都是错误的,等同于语法错误。让我们先解决一下你丢失空格或额外换行的明显地方:

proc fac {x} {
if {$x<2} {
 return 1
} else {
return $x[fac [incr x -1]]
}
}

现在将计算某些内容(我们通过在if及其第一个参数之间添加x和{之间的空格来摆脱语法问题在-1的参数中,incrfac之间的递归调用中的{1}},以及[incr …]之后的额外换行符,但它仍然没有您想要的是什么,因为它不会else乘以$x;添加(使用[fac [incr x -1]])给我们这个:

[expr {… * …}]

现在我们已经有了实际的功能因素!为了清晰起见,我们快速整理缩进:

proc fac {x} {
if {$x<2} {
 return 1
} else {
return [expr {$x * [fac [incr x -1]]}]
}
}

有更有效的方法来实现阶乘,但至少现在这是一个干净的工作示例。

通常,在修复脚本时,您应首先修复语法错误(Tcl关心空格和换行符以及它们之间的区别),然后修改语义错误(例如,缺少乘法),然后修改缩进。但有时修复缩进会使语法错误更明显,因此命令不是严格的规则!

您可能想要查找并安装nagelfar tool的副本。这会进行语法分析,并会为您找到代码中的各种错误。