Tcl:使用未知命令来包含点符号程序
Tcl: Using the unknown command to include dot notation procedures
Tcl 语法在其命令/参数结构的意义上非常简单和一致。有时我会想念其他语言的点符号,例如 ruby。在 ruby 你可以纠正这样的事情:
-199.abs # => 199
"ice is nice".length # => 11
"ruby is cool.".index("u") # => 1
"Nice Day Isn't It?".downcase.split("").uniq.sort.join # => " '?acdeinsty"
在Radical Language Modification and Let unknown know中有关于如何使用未知命令修改语言的想法,例如:
proc know {cond body} {
proc unknown {args} [string map [list @c@ $cond @b@ $body] {
if {![catch {expr {@c@}} res] && $res} {
return [eval {@b@}]
}
}][info body unknown]
}
know {[regexp {^([a-z]+)\.([a-z]+)$} [lindex $args 0] -> from to]} {
set res {}
while {$from<=$to} {lappend res $from; incr from}
set res
}
# % puts [1..5]
# 1 2 3 4 5
如何修改以前的代码,以便我可以像 Ruby 示例中那样使用点符号编写命令。
您可以针对特定 操作执行此操作,但不是全部,并且存在一些句法限制。例如:
know {[regexp {^(.*)\.length$} [lindex $args 0] -> value]} {
string length $value
}
puts [abc.length]
# ---> 3
set thevar "abc def"
puts [$thevar.length]
# ---> 7
puts ["abc def".length]
# ---> extra characters after close-quote
也就是说,该值必须仍然是句法有效的 Tcl;最后一个例子不是。您可以通过在处理程序中使用 [$value]
而不是普通的 $value
来链接 know
处理程序,前提是您有基本情况的处理程序。
know {[regexp {^(.*)\.length$} [lindex $args 0] -> value]} {
string length [$value]
}
know {[regexp {^(.*)\.repeat\((\d+)\)$} [lindex $args 0] -> value count]} {
string repeat [$value] $count
}
# Base case for simple words
know {[regexp {^'(.*)'$} [lindex $args 0] -> value]} {
set value
}
puts ['abc\ def'.repeat(5).length]
# ---> 35
最终,虽然您可以做各种各样的事情,但这并不是 Tcl 设计的工作方式。它会很慢(unknown
调用机制不是优化路径)并且你会遇到限制。最好学会以正常方式做事:
puts [string length [string repeat "abc def" 5]]
Tcl 语法在其命令/参数结构的意义上非常简单和一致。有时我会想念其他语言的点符号,例如 ruby。在 ruby 你可以纠正这样的事情:
-199.abs # => 199
"ice is nice".length # => 11
"ruby is cool.".index("u") # => 1
"Nice Day Isn't It?".downcase.split("").uniq.sort.join # => " '?acdeinsty"
在Radical Language Modification and Let unknown know中有关于如何使用未知命令修改语言的想法,例如:
proc know {cond body} {
proc unknown {args} [string map [list @c@ $cond @b@ $body] {
if {![catch {expr {@c@}} res] && $res} {
return [eval {@b@}]
}
}][info body unknown]
}
know {[regexp {^([a-z]+)\.([a-z]+)$} [lindex $args 0] -> from to]} {
set res {}
while {$from<=$to} {lappend res $from; incr from}
set res
}
# % puts [1..5]
# 1 2 3 4 5
如何修改以前的代码,以便我可以像 Ruby 示例中那样使用点符号编写命令。
您可以针对特定 操作执行此操作,但不是全部,并且存在一些句法限制。例如:
know {[regexp {^(.*)\.length$} [lindex $args 0] -> value]} {
string length $value
}
puts [abc.length]
# ---> 3
set thevar "abc def"
puts [$thevar.length]
# ---> 7
puts ["abc def".length]
# ---> extra characters after close-quote
也就是说,该值必须仍然是句法有效的 Tcl;最后一个例子不是。您可以通过在处理程序中使用 [$value]
而不是普通的 $value
来链接 know
处理程序,前提是您有基本情况的处理程序。
know {[regexp {^(.*)\.length$} [lindex $args 0] -> value]} {
string length [$value]
}
know {[regexp {^(.*)\.repeat\((\d+)\)$} [lindex $args 0] -> value count]} {
string repeat [$value] $count
}
# Base case for simple words
know {[regexp {^'(.*)'$} [lindex $args 0] -> value]} {
set value
}
puts ['abc\ def'.repeat(5).length]
# ---> 35
最终,虽然您可以做各种各样的事情,但这并不是 Tcl 设计的工作方式。它会很慢(unknown
调用机制不是优化路径)并且你会遇到限制。最好学会以正常方式做事:
puts [string length [string repeat "abc def" 5]]