tcl:proc body用引号代替花括号
如果过程的主体以引号而不是花括号提供,是否存在任何问题(例如性能惩罚) 我的代码在其他程序内部生成程序(类似OOP的方法),例如tcl:proc body用引号代替花括号,tcl,proc,Tcl,Proc,如果过程的主体以引号而不是花括号提供,是否存在任何问题(例如性能惩罚) 我的代码在其他程序内部生成程序(类似OOP的方法),例如 proc dataObject {name someData} { # more stuff proc ${name}.getData {args} \ "checkArgs \$args 0; return $someData" # more stuff } 为了简单起见,我使用引号来启用变量替换。这是可行的,但我只是担心代
proc dataObject {name someData} {
# more stuff
proc ${name}.getData {args} \
"checkArgs \$args 0; return $someData"
# more stuff
}
为了简单起见,我使用引号来启用变量替换。这是可行的,但我只是担心代码可能不会被预编译或其他什么
谢谢你的帮助
我只是担心代码可能不会被预编译或者其他什么
这是不需要担心的,此外,Tcl中没有预编译或类似的功能。一旦第一次执行,生成的proc主体将被字节编译(不管主体脚本是如何组装的)
但是,您的proc生成器并不健壮。当someData
包含导致正文脚本或其某个命令不完整的字符串时,引号下的变量替换将中断正文脚本,例如:
dataObject test "do it"
将失败,因为它转化为
return do it;
有几种方法可以稳健地组合脚本(命令序列字符串),一种是使用list
保护:
proc dataObject {name someData} {
set procName ${name}.getData
append body {checkArgs $args 0} \;
append body [list return $someData] \;
proc $procName {args} $body
return [namespace which -command $procName]
}
正如Donal所指出的,嵌套过程调用一个接一个并不一定会导致您所期望的结果。不过,在您的情况下,作为一个生成器,它可能是可以接受的。不过,您可能需要考虑使用TCL lambda或适当的(良好的,数据)对象?
我只是担心代码可能不会被预编译或者其他什么
这是不需要担心的,此外,Tcl中没有预编译或类似的功能。一旦第一次执行,生成的proc主体将被字节编译(不管主体脚本是如何组装的)
但是,您的proc生成器并不健壮。当someData
包含导致正文脚本或其某个命令不完整的字符串时,引号下的变量替换将中断正文脚本,例如:
dataObject test "do it"
将失败,因为它转化为
return do it;
有几种方法可以稳健地组合脚本(命令序列字符串),一种是使用list
保护:
proc dataObject {name someData} {
set procName ${name}.getData
append body {checkArgs $args 0} \;
append body [list return $someData] \;
proc $procName {args} $body
return [namespace which -command $procName]
}
正如Donal所指出的,嵌套过程调用一个接一个并不一定会导致您所期望的结果。不过,在您的情况下,作为一个生成器,它可能是可以接受的。不过,您可能需要考虑使用TCL lambda或适当的(良好的,数据)对象?很难完全可靠的代码生成,但不可能,并且在程序主体周围使用双引号是完全合法的。我建议在执行codegen之前,将插入单词的空格限制为非空字母数字;几乎所有的恶作剧都停止了;需要引用其他值(只要稍加鼓励,
list
命令就可以准确地引用所需的值)。通常更容易生成一个别名,在非可变过程的调用中插入一些额外的参数。这里有一个非常简单的例子来说明我的意思:
proc saySomething {a b} {
puts -nonewline $a
puts $b
}
proc makeSpeaker {cmd prefix} {
interp alias {} $cmd {} saySomething "[string trimright $prefix] "
}
makeSpeaker hello "Hello to"
hello Ralf
# ==> Hello to Ralf
正如您所看到的,我们已经“生成”了一段代码,其中包含一个带有空格的单词,而不必进行复杂的引用。它不能做所有的事情,但它可以做很多
不要编写自己的伪OO代码。现在不行。Tcl从8.6版开始就提供了一个OO系统核心,它使做这些事情更快、更可靠
oo::class create Speaker {
variable Prefix
constructor {prefix} {
set Prefix "[string trimright $prefix] "
}
method say {suffix} {
puts -nonewline $Prefix
puts $suffix
}
}
Speaker create greeting "Hello to"
greeting say Ralf
当然,您可以将这两种方法混合在一起,以获得一些真正强大的方法,但是为了快速理解,示例变得有点长…很难完全可靠地生成代码,但并非不可能,在过程体周围使用双引号是完全合法的。我建议在执行codegen之前,将插入单词的空格限制为非空字母数字;几乎所有的恶作剧都停止了;需要引用其他值(只要稍加鼓励,
list
命令就可以准确地引用所需的值)。通常更容易生成一个别名,在非可变过程的调用中插入一些额外的参数。这里有一个非常简单的例子来说明我的意思:
proc saySomething {a b} {
puts -nonewline $a
puts $b
}
proc makeSpeaker {cmd prefix} {
interp alias {} $cmd {} saySomething "[string trimright $prefix] "
}
makeSpeaker hello "Hello to"
hello Ralf
# ==> Hello to Ralf
正如您所看到的,我们已经“生成”了一段代码,其中包含一个带有空格的单词,而不必进行复杂的引用。它不能做所有的事情,但它可以做很多
不要编写自己的伪OO代码。现在不行。Tcl从8.6版开始就提供了一个OO系统核心,它使做这些事情更快、更可靠
oo::class create Speaker {
variable Prefix
constructor {prefix} {
set Prefix "[string trimright $prefix] "
}
method say {suffix} {
puts -nonewline $Prefix
puts $suffix
}
}
Speaker create greeting "Hello to"
greeting say Ralf
当然,您可以将这两种方法混合在一起,以获得一些真正强大的方法,但是为了快速理解,示例变得有点长…非常感谢,非常有用的提示和更优雅的解决方案。我可以问你:当你提到一个“适当的对象”时,你在想什么样的Tcl结构吗?
:oo::object
和::oo::class
,正如Donal所指出的。请看我对Donal Fellows回答的评论:它更像是一个模块,而不是类的对象。对于Tcl中的模块机制有什么建议吗?非常感谢,非常有用的提示和更优雅的解决方案。我可以问你:当你提到一个“适当的对象”时,你在想什么样的Tcl结构吗?:oo::object
和::oo::class
,正如Donal所指出的。请看我对Donal Fellows回答的评论:它更像是一个模块,而不是类的对象。对Tcl中的模块机制有什么建议吗?当你可以直接使用时,为什么OOP喜欢这些东西?当你可以直接使用时,为什么OOP喜欢这些东西?非常感谢,非常有用,一如既往。我会考虑切换到代码> OO。不过,我很难理解你的第一个例子。可能interp
手册页中的这句话是至关重要的:“源命令的命令过程获取其参数,并将其与别名的targetCmd和args合并,以创建一个新的参数数组。”?我曾想过切换到oo
,但我注意到我的“方法”是更像是模块的函数,而不是对象的方法,因为只有一个实例。因此,定义一个类并不意味着