#arguments #tcl #whitespace
#аргументы #tcl #пробел
Вопрос:
Просто для развлечения я написал следующий фрагмент кода:
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
Мне показалось забавным, что имена процедур могут содержать пробелы. Я подумал, что объединение этого с практически неиспользуемыми аргументами позволило бы сделать программы Tcl очень похожими на разговорный естественный язык, аналогично Smalltalk с его bakeACake forPeople: 3 andChildren: 3
, только без странного двоеточия, нарушающего предложения, и неестественного порядка слов.
Чтобы изучить эту идею дальше, я попробовал тот же шаблон для параметров процедуры, заменив каждый из них _
простым пробелом. 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
? - Можно ли было бы написать,
spaceproc
что допускает этот синтаксический вариант?
Ответ №1:
Внимательно прочитайте proc
документацию: каждое из аргументов в списке аргументов само по себе является списком, который должен содержать 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» (если вы не вникаете в «ансамбли пространств имен»)
Комментарии:
1. Вы могли бы использовать
${for people}
… но, как и большинство программистов, мы ленивы.