反向打印列表:TCL
Print List in Reverse: TCL
我正在阅读 Don Libes 的 "Exploring Expect: A TCL-Based Toolkit ... "。
向 "Write a procedure to reverse a string. If you wrote an iterative solution, now write a recursive solution or vice versa."
提出的章节结尾问题
读到现在,我决定尝试以下方法:
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" 变量,尽管我不确定为什么。
另外,这种方法是递归的还是迭代的?
任何建议将不胜感激。
________SOLUTION____________________________________
根据@glenn提供的solution/approach正确代码如下:
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]
}
下面他的 post 显示了许多其他示例。
首先,您要将 3 个参数传递给 incr:$index
、-
和 1
。如错误消息所示,incr 最多接受 2 个参数。将 "minus 1" 指定为 -1
,不带空格。
注意错误信息:
wrong # args: should be "incr varName ?increment?"
注意它是怎么说的 varName
——当您使用 $index
时,您传递的是变量的 value 而不是 name。删除 $
for {set i [expr {[llength $list]-1}]} {$i>=0} {incr i -1} {
# .................................................. ^ ^^
# varname increment
请注意 expr 参数周围的大括号:这是养成的好习惯。
这里有几个不同的实现 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
我正在阅读 Don Libes 的 "Exploring Expect: A TCL-Based Toolkit ... "。
向 "Write a procedure to reverse a string. If you wrote an iterative solution, now write a recursive solution or vice versa."
提出的章节结尾问题读到现在,我决定尝试以下方法:
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" 变量,尽管我不确定为什么。 另外,这种方法是递归的还是迭代的?
任何建议将不胜感激。
________SOLUTION____________________________________
根据@glenn提供的solution/approach正确代码如下:
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]
}
下面他的 post 显示了许多其他示例。
首先,您要将 3 个参数传递给 incr:$index
、-
和 1
。如错误消息所示,incr 最多接受 2 个参数。将 "minus 1" 指定为 -1
,不带空格。
注意错误信息:
wrong # args: should be "incr varName ?increment?"
注意它是怎么说的 varName
——当您使用 $index
时,您传递的是变量的 value 而不是 name。删除 $
for {set i [expr {[llength $list]-1}]} {$i>=0} {incr i -1} {
# .................................................. ^ ^^
# varname increment
请注意 expr 参数周围的大括号:这是养成的好习惯。
这里有几个不同的实现 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