Синтаксически необходимы четкие открытые и закрытые разделители?
Проводя аналогию между умными кавычками и языками программирования, мне пришло в голову, что разные символы для открытия и закрытия разделителей могут быть не нужны, а просто выбор в читаемости.
Например, аргументы в анонимные функции Rubys используют одинаковые каналы для открытия и закрытия. Haskell использует пробел с крайними предрассудками.
Я не спрашиваю, нужны ли разные типы разделителей - скобки для индексировщиков, фигурные скобки для блоков - но существуют ли сильные и сильные синтаксически сильные различные открытые и закрытые фигурные скобки (например, (
и )
) на большинстве языков или просто предпочтение дизайнеров.
Ответы
Ответ 1
Не синтаксически необходимо, но если открытые и закрытые разделители одинаковы, это затрудняет (или невозможно) вложение вещей. Приложение A представляет собой оболочку POSIX,
где
var=`command`
заменил на
var=$(command)
именно потому, что код с идентичными ограничителями открытия и закрытия не вложен.
Ответ 2
Наличие отдельных разделителей допускает вложенность. Список параметров блока Ruby не поддерживает вложенность, поэтому использование одного и того же разделителя в порядке.
Ответ 3
В C и С++ оголенные фигурные скобки могут быть вложенными и открытыми вложенными лексическими областями:
{
int a = 42;
{
int a = 24;
{
printf("%d\n", a); // prints 24
}
}
}
Используйте одинаковые разделители, и это неоднозначно:
|
int a = 42;
|
int a = 24;
| // Is this an open or close pipe?
printf("%d\n", a); // 24? 42?
| // could be a pair
| // of open+close
|
Учитывая преобладание синтаксических правил C, вероятно, будет много других языков с подобными проблемами (perl, для одного).
Ответ 4
print |foo|bar||
Может означать либо:
print (foo(bar))
или
print (foo)bar()
Оба из них действительны для Haskell и имеют разные значения. Но вы спрашиваете, можно ли в принципе изменить язык, чтобы он не требовал этого?
Хорошо, что вы можете сделать нечитаемую вещь. Вместо применения функций с сопоставлением введите префикс, оператор с двумя аргументами для приложения, назовите его *
. Тогда:
foo (bar (baz quux)) bax
может быть однозначно записано:
* * foo * bar * baz quux bax
Приложение и один символ константы достаточно, чтобы закодировать вычисление комбинатора, так что технически, нет, вам вообще не нужны скобки (машины Тьюринга также не нуждаются в круглых скобках).
Но вы не можете просто сгладить все круглые скобки в барах и сделать это однозначно.
Ответ 5
Unlambda является примером для языка без скобок, фигурных скобок и т.д. Они заменяются одним оператором (Backtick), который стоит для "применять". Аналогично, в Haskell вы можете написать a $ b c
вместо a (b c)
. Таким образом, есть способы избежать разных разделителей.
Ответ 6
Глядя на это с точки зрения разработчика, пишущего компилятор, я считаю, что проще использовать разделители. Я не совсем понимаю, что вы подразумеваете под разными разделителями, но вы можете технически использовать все, что вам нравится, в качестве символов на вашем языке. Просто посмотрите этот язык здесь. Просто посмотрите, насколько проще разбирать оператор if, когда он имеет открывающие и закрывающие фигурные скобки:
if (true)
{
doSomething();
thenDoSomethingElse();
}
в отличие от:
if true
doSomething
thenDoSomethingElse
Помимо табуляции, как еще мне показать, что я хочу, чтобы оба этих метода выполнялись как часть тела if
. Скобки дают понять парсеру, что все это происходит вместе. Проблема с языками, которые делают это, - это "проблема с болтающимися остатками":
if true
if someCondition
doSomething
else
doSomethingElse
Лучше сделать ваш синтаксический анализатор достаточно умным, чтобы знать, как совместить этот оператор else. Я думаю, что явные разделители делают это проще.
Ответ 7
Как уже упоминалось, они не нужны. Существуют и другие способы указать, когда начинается/заканчивается блок. При этом различные разграничители открывания и закрытия предоставляют больше информации людям, читающим код по очень маленькому коду. Эта информация может не только помочь читателю понять, что делает код, но и то, что было предназначено для.
В качестве примера этого, многие стандарты кодирования требуют скобок вокруг одного оператора, если блоки в C.