Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
tcl:proc body用引号代替花括号_Tcl_Proc - Fatal编程技术网

tcl:proc body用引号代替花括号

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 } 为了简单起见,我使用引号来启用变量替换。这是可行的,但我只是担心代

如果过程的主体以引号而不是花括号提供,是否存在任何问题(例如性能惩罚)

我的代码在其他程序内部生成程序(类似OOP的方法),例如

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
,但我注意到我的“方法”是更像是模块的函数,而不是对象的方法,因为只有一个实例。因此,定义一个类并不意味着