为什么Tcl允许proc名称带有空格,但不允许参数带有空格?

时间:2019-04-01 21:22:29

标签: arguments tcl whitespace

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

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

1 个答案:

答案 0 :(得分:3)

请仔细阅读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”开头的命令(除非您深入研究“命名空间集成”)