【问题标题】:Why does Tcl allow proc names with spaces, but not parameters with spaces?为什么 Tcl 允许带有空格的 proc 名称,但不允许带有空格的参数?
【发布时间】:2019-04-01 21:22:29
【问题描述】:

只是为了好玩,我写了以下代码:

proc "bake a cake" {"number_of_people" {number_of_children}} {
    set fmt "Take %d pounds of flour and %d bags of marshmallows."
    puts [format $fmt "${number_of_people}" ${number_of_children}]
    puts "Put them into the oven and hope for the best."
}

"bake a cake" 3 3
{bake a cake} 5 0

我发现 proc 名称可能包含空格很有趣。我认为将它与基本上未使用的参数结合起来可以使 Tcl 程序看起来与口语自然语言非常相似,就像 Smalltalk 对其bakeACake forPeople: 3 andChildren: 3 所做的那样,只是没有奇怪的冒号干扰句子和不自然的词序.

为了进一步探索这个想法,我对 proc 的参数尝试了相同的模式,将每个 _ 替换为一个简单的空格。 tclsh8.6 不喜欢:

too many fields in argument specifier "number of people"
    (creating proc "bake a cake")
    invoked from within
"proc "bake a cake" {"number of people" {number of children}} {
        set fmt "Take %d pounds of flour and %d bags of marshmallows."
        puts [format $fmt "${n..."
    (file "bake.tcl" line 1)

这引发了以下问题:

  • 是否有令人信服的理由说明为什么 proc 名称可以包含空格但参数名称不能?
  • 只是proc的一个实现细节吗?
  • 是否可以编写spaceproc 来允许这种语法变体?

【问题讨论】:

    标签: arguments tcl whitespace


    【解决方案1】:

    仔细阅读proc 文档:arg 列表中的每个 args 本身就是一个列表,它必须具有 1 或 2 个元素:强制参数名称和可选的默认值。 "number of people" 的元素太多。再多一层大括号就可以得到你想要的:

    % proc "bake a cake" {{"for people"} {"and children"}} {
        puts "baking a cake for [set {for people}] people and [set {and children}] children"
    }
    % "bake a cake" 1 2
    baking a cake for 1 people and 2 children
    % "bake a cake"
    wrong # args: should be "{bake a cake} {for people} {and children}"
    

    我没有看到进行这个实验的好处:笨拙的变量名排除了$ 语法糖。

    请注意,获得类似 Smalltalk 的代码并不难

    % proc bakeACake {forPeople: nPeople andChildren: nChildren} {
        if {[set forPeople:] ne "forPeople:" || [set andChildren:] ne "andChildren:"} {
            error {should be "bakeACake forPeople: nPeople andChildren: nChildren"}
        }
        puts "baking a cake for $nPeople people and $nChildren children"
    }
    % bakeACake
    wrong # args: should be "bakeACake forPeople: nPeople andChildren: nChildren"
    % bakeACake foo 1 bar 2
    should be "bakeACake forPeople: nPeople andChildren: nChildren"
    % bakeACake forPeople: 3 andChildren: 4
    baking a cake for 3 people and 4 children
    

    虽然与 Smalltalk 不同,您不能有其他以“bakeACake”开头的命令(除非您深入研究“命名空间集合”)

    【讨论】:

    • 你可以使用${for people}……但像大多数程序员一样,我们很懒。
    猜你喜欢
    • 2015-04-10
    • 1970-01-01
    • 2019-06-04
    • 2020-03-11
    • 2012-01-09
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2016-10-14
    相关资源
    最近更新 更多