如何从 -command 选项中的代码获取结果
How to get result from code in a -command option
参考: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 选项获得 return 过程结果?
对不起,英语很难读,谢谢。
P.S。我想 "cmd",可能是 "Macro" 中的其他语言(如 C 风格)?
你的问题是:
proc fac {x} {
if{$x<2} {
return 1
} else
{
return $x[fac[incr x-1]]
}
}
不计算阶乘。是的,它正在声明一个过程,fac
,但是该过程的实现脚本在多个方面都是错误的,这等同于语法错误。让我们首先修复明显缺少 spaces 或额外换行符的地方:
proc fac {x} {
if {$x<2} {
return 1
} else {
return $x[fac [incr x -1]]
}
}
现在将计算 something(我们通过在 if
和它的第一个参数之间添加 space 来摆脱语法问题x
和 -1
在 incr
的参数中,在递归调用中在 fac
和 [incr …]
之间,并在 [=21= 之后去掉额外的换行符]) 但它仍然不是您想要的,因为它没有将 $x
乘以 [fac [incr x -1]]
;添加那个([expr {… * …}]
)给我们这个:
proc fac {x} {
if {$x<2} {
return 1
} else {
return [expr {$x * [fac [incr x -1]]}]
}
}
现在我们得到了一个实际起作用的阶乘!为了清楚起见,让我们快速整理一下缩进:
proc fac {x} {
if {$x<2} {
return 1
} else {
return [expr {$x * [fac [incr x -1]]}]
}
}
有更有效的方法来实现阶乘,但至少现在这是一个干净的工作示例。
一般来说,在修复你的脚本时,你应该首先修复语法错误(Tcl 关心 spaces 和换行符以及它们之间的区别),然后是你的语义错误(例如,一个缺失的乘法),然后是你的缩进。但有时修复缩进会使语法错误更加明显,因此该顺序不是严格的规则!
您可能想要查找并安装 nagelfar tool 的副本。那会进行语法分析,并会为您找出代码中的各种错误。
参考: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 选项获得 return 过程结果?
对不起,英语很难读,谢谢。
P.S。我想 "cmd",可能是 "Macro" 中的其他语言(如 C 风格)?
你的问题是:
proc fac {x} {
if{$x<2} {
return 1
} else
{
return $x[fac[incr x-1]]
}
}
不计算阶乘。是的,它正在声明一个过程,fac
,但是该过程的实现脚本在多个方面都是错误的,这等同于语法错误。让我们首先修复明显缺少 spaces 或额外换行符的地方:
proc fac {x} {
if {$x<2} {
return 1
} else {
return $x[fac [incr x -1]]
}
}
现在将计算 something(我们通过在 if
和它的第一个参数之间添加 space 来摆脱语法问题x
和 -1
在 incr
的参数中,在递归调用中在 fac
和 [incr …]
之间,并在 [=21= 之后去掉额外的换行符]) 但它仍然不是您想要的,因为它没有将 $x
乘以 [fac [incr x -1]]
;添加那个([expr {… * …}]
)给我们这个:
proc fac {x} {
if {$x<2} {
return 1
} else {
return [expr {$x * [fac [incr x -1]]}]
}
}
现在我们得到了一个实际起作用的阶乘!为了清楚起见,让我们快速整理一下缩进:
proc fac {x} {
if {$x<2} {
return 1
} else {
return [expr {$x * [fac [incr x -1]]}]
}
}
有更有效的方法来实现阶乘,但至少现在这是一个干净的工作示例。
一般来说,在修复你的脚本时,你应该首先修复语法错误(Tcl 关心 spaces 和换行符以及它们之间的区别),然后是你的语义错误(例如,一个缺失的乘法),然后是你的缩进。但有时修复缩进会使语法错误更加明显,因此该顺序不是严格的规则!
您可能想要查找并安装 nagelfar tool 的副本。那会进行语法分析,并会为您找出代码中的各种错误。