Действительно, есть несколько мест, где пантезы являются неестественными в Лиспе. Обычно правила очень непротиворечивы: в скобках начинается список, а первым элементом списка является функция, которая будет использоваться со всеми остальными элементами списка в качестве параметров.
Эта согласованность также поддерживается для большинства макросов и специальных форм, и это делает код на Лиспе очень однородным ... однако в некоторых макросах и специальных операторах круглые скобки имеют различное значение и используются для группировки ... например
(dolist (x L) (print x))
в этом случае, например, x
в первом пантезе НЕ является функцией, которая должна вызываться, передавая L
в качестве аргумента. Другой пример -
(let ((x 10)
(y 20))
(print (+ x y)))
В этом случае скобки используются только для группировки, и первый элемент (x 10)
явно не является функцией, которую нужно применить, и ее первый элемент x
также не является функцией.
labels
работает точно так же, как let
, и, по-видимому, для группировки требуется «лишняя» скобка, если определено более одной функции.
Хотя эти особые случаи действительно несколько раздражают, их очень мало, и после написания некоторого количества кода на Лиспе вы их усвоите и просто поймете правильно, не задумываясь.
Это, тем не менее, асимметрия, которая, например, очень затрудняет написание корректного обходчика кода, а также часто, когда вы совершаете ошибку в этой «области синтаксиса» Lisp, к сожалению, сообщение об ошибке не очень помогает указать вам на ошибка.
Эта «сложность», конечно, просто ничто по сравнению с другими языками (и давайте не будем обсуждать, насколько ясны сообщения, когда вы делаете ошибку в шаблоне C ++ ;-)).
Я думаю, что не совсем верно, что синтаксис Lisp "тривиален" или даже просто отсутствует. Синтаксис Lisp присутствует, даже если не на уровне символов, а на уровне форм Lisp, и он почти тривиален, за исключением нескольких специальных форм и макросов.