我正在阅读Don Libes撰写的“探索期望:基于TCL的工具包...”。
本章末尾的问题要求“编写一个过程以反转字符串。如果您编写了迭代解决方案,请现在编写递归解决方案,反之亦然。”
阅读到现在为止,我决定尝试以下操作:
set list {a b c d e f g}
for {set index [expr [llength $list]-1]} {$index>=0} {incr $index - 1} {
for {set i [expr [llength $list]-1]} {$i>=0} {incr $i - 1} {
puts [lindex $list $index]
}
}
但是出现以下错误:
Error(s), warning(s):
wrong # args: should be "incr varName ?increment?"
while executing
"incr $i - 1"
("for" body line 3)
invoked from within
"for {set index [expr [llength $list]-1]} {$index>=0} {incr $index - 1} {
for {set i [expr [llength $list]-1]} {$i>=0} {incr $i - 1} {
puts [lind..."
(file "source_file.tcl" line 4)
g
虽然我不确定为什么,但是我发现我没有正确地添加“ index”变量。 另外,这种方法是递归还是迭代?
任何建议将不胜感激。
________解决方案____________________________________
基于@glenn提供的解决方案/方法,正确的代码如下:
set list {a b c d e f g}
for {set i [expr {[llength $list]-1}]} {$i>=0} {incr i -1} {
puts [lindex $list $i]
}
他的帖子中还显示了许多其他示例。
答案 0 :(得分:1)
首先,您要将3个参数传递给incr:enum { OUTSIDE_BSPH = 0, INSIDE_BSPH = 1 };
bool bsph = true;
//...
bsph = false;
f(OUTSIDE_BSPH, arg1, arg2, arg3, arg4, arg5);
if (bsph) {
f(INSIDE_BSPH, arg1, arg2, arg3, arg4, arg5);
}
g(OUTSIDE_BSPH, arg6, arg7, arg8);
if (bsph) {
g(INSIDE_BSPH, arg6, arg7, arg8);
}
h(OUTSIDE_BSPH, arg3, arg4, arg5);
if (bsph) {
h(INSIDE_BSPH, arg3, arg4, arg5);
}
// ...
,caller(bsph, f, arg1, arg2, arg3, arg4, arg5);
caller(bsph, g, arg6, arg7, arg8);
caller(bsph, h, arg3, arg4, arg5);
// ...
和 <div id="google_translate_element"></div><script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement({pageLanguage: 'en', includedLanguages: 'es', layout: google.translate.TranslateElement.InlineLayout.SIMPLE}, 'google_translate_element');
}
</script><script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
。如错误消息所示,incr最多接受2个参数。将“负1”指定为$index
,不带空格。
请注意错误消息:
-
请注意1
的说法-使用-1
时,您传递的是变量的 value 而不是 name 。删除wrong # args: should be "incr varName ?increment?"
varName
请注意expr参数周围的花括号:这是一个很好的习惯。
答案 1 :(得分:1)
以下是lreverse
递归
proc lreverse_rec {list} {
if {[llength $list] == 0} return
set procname [lindex [info level 0] 0]
return [concat [lindex $list end] [$procname [lrange $list 0 end-1]]]
}
尾递归
proc lreverse_tail {list {result {}}} {
if {[llength $list] == 0} {return $result}
lappend result [lindex $list end]
set procname [lindex [info level 0] 0]
tailcall $procname [lrange $list 0 end-1] $result
}
while循环a(来自本主题的very old discussion)
proc lreverse_while_a {xlist} {
set rlist $xlist
for {
set j 0
set i [expr {[llength $xlist]-1}]
} {$i>=0} {
incr i -1
incr j
} {
set rlist [lreplace $rlist[set rlist {}] $j $j [lindex $xlist $i]]
}
set rlist
}
while循环b
proc lreverse_while_b {list} {
set result {}
while {[llength $list]} {
lappend result [lindex $list end]
set list [lrange $list[set list {}] 0 end-1]
}
return $result
}
while循环,但具有一些便利的list-op procs
proc pop {listVar} {
upvar 1 $listVar list
set result [lindex $list end]
set list [lrange $list[set list {}] 0 end-1]
return $result
}
proc push {listVar value} {
upvar 1 $listVar list
lappend list $value
}
proc shift {listVar} {
upvar 1 $listVar list
set result [lindex $list 0]
set list [lrange $list[set list {}] 1 end]
return $result
}
proc unshift {listVar value} {
upvar 1 $listVar list
set list [linsert $list[set list {}] 0 $value]
}
所有这些都导致了整洁的解决方案
proc lreverse_listops {list} {
set result {}
while {[llength $list]} {push result [pop list]}
return $result
}
我无法把手放在解释set list [... $list[set list {}] ...]
惯用语的网页上,但是当您对一个值进行突变时,它是对Tcl内部的一种优化。更新:这里是:https://wiki.tcl-lang.org/page/K(感谢mrcalvin)
一些基准测试
## put all the above procedures here ...
proc main {} {
set list [list]
for {set i 0} {$i <= 100} {incr i} {lappend list $i}
foreach proc {
lreverse_rec
lreverse_tail
lreverse_while_a
lreverse_while_b
lreverse_listops
} {
puts [format "%-20s %s" $proc [time [list $proc $list] 1000]]
}
}
main
输出类似
lreverse_rec 271.029 microseconds per iteration
lreverse_tail 293.496 microseconds per iteration
lreverse_while_a 75.541 microseconds per iteration
lreverse_while_b 53.962 microseconds per iteration
lreverse_listops 247.262 microseconds per iteration