Что потеряет Клоджур, если откажется от ведущих скобок, таких как Дилан, Джулия и Сеф?


Три шепелявых гомойконических языка, Дилан, Julia и Seph все отошли от ведущей скобки - так что гипотетический вызов функции в Common Lisp будет выглядеть так:

(print hello world)

Будет выглядеть следующим гипотетическим вызовом функции

print(hello world)

На трех упомянутых выше языках.

Если бы Клоджур пошел по этому пути - чем бы он пожертвовал, чтобы попасть туда?

Рассуждение: Помимо удивительных ленивых функциональных данных структуры в Clojure и улучшенный синтаксис для карт и seqs, языковая поддержка параллелизма, платформа JVM, инструментарий и потрясающее сообщество-отличительной особенностью этого "Лиспа" является ведущая скобка, дающая гомоиконичность, которая дает макросы, обеспечивающие синтаксическую абстракцию.

Но если вам не нужны ведущие скобки-зачем они нужны? Единственные аргументы, которые я могу придумать для их сохранения, - это

(1) повторное использование инструментальной поддержки в emacs

(2) подсказка люди, чтобы "думать на Лиспе" , а не пытаться рассматривать его как другой процедурный язык)

9 24

9 ответов:

Писать макросы стало бы намного сложнее, потому что структура больше не была бы простой вам быпонадобился другой способ кодирования, где выражения начинаются и заканчиваются используя некоторый синтаксический символ для обозначения начала и конца выражений вы можетенаписать код, который генерирует выражения Возможно, вы могли бы решить эту проблему, добавив что-то вроде ( для обозначения начала выражения...

Под совершенно другим углом зрения стоит посмотреть на это видео на разница между знакомым и легким делая синтаксис lisps более знакомым не сделает его более легким для людей, чтобы узнать и может ввести в заблуждение, если это выглядит очень похоже на то, что это не так.

Даже если вы полностью не согласны, это видео стоит часа.

Простого перемещения скобок на один атом для вызовов функций будет недостаточно, чтобы удовлетворить кого-либо; люди будут жаловаться на отсутствие операторов инфикса, блоков begin/end и т. д. Кроме того, вам, вероятно, придется вводить запятые / разделители во всех местах.

Дайте им это, и макросы будет гораздо труднее просто писать правильно (и, вероятно, будет еще труднее писать макросы, которые выглядят и действуют красиво со всем новым синтаксисом, который вы ввели к тому времени). А макросы-нет что-то приятное, что вы можете игнорировать или сделать намного более раздражающим; весь язык (как и любой другой Lisp) построен прямо на них. Большинство "видимых пользователем" вещей, которые есть в clojure.ядра, в том числе давайте, деф, определение и т. д. макросы.

(похвала ответу Эндрю Кука, который предоставил ссылку на проект Уилера и Глории "читаемые S-выражения Lisp")

Ссылка выше-это проект, предназначенный для обеспечения читаемого синтаксиса для всех языков, основанных на s-выражениях, включая Scheme и Clojure. Вывод состоит в том, что это можно сделать: есть способ иметь читаемый Lisp без скобок.

В основном то, что делает проект Дэвида Уилера, - это добавление синтаксического сахара в Лисп-подобные языки. обеспечить более современным синтаксисом, таким образом, что не нарушить поддержка Lisp для предметно-ориентированных языков. Усовершенствования являются необязательными и обратно совместимыми, поэтому вы можете включать их в любое количество или в меньшем количестве и смешивать с существующим кодом.

Этот проект определяет три новых типа выражений:
  • фигурно-инфиксные выражения. (+ 1 2 3) становится {1 + 2 + 3} в любом месте вы хотите использовать операторы инфикса любой арности. (Есть особый случай, который должен быть обрабатывается с осторожностью, если встроенное выражение использует несколько операторов, таких как {1 + 2 * 3} - хотя {1 + {2 * 3} } работает, как и ожидалось).
  • новейший выражений. (f x y) становится f(x y) (требуется, чтобы между именем функции и ее параметрами не было пробела)
  • сладкие выражения. Открывающие и закрывающие родительские элементы могут быть заменены (необязательно) питоноподобным семантическим отступом. Сладкие выражения можно свободно смешивать с традиционными скобками s-выражение.
Результатом является Лисп-совместимый, но гораздо более читаемый код. Пример того, как новый синтаксический сахар повышает читабельность:
(define (gcd_ a b)
    (let (r (% b a))
        (if (= r 0) a (gcd_ r a))))

(define-macro (my-gcd)
    (apply gcd_ (args) 2))

Становится:

define gcd_(a b)
    let r {b % a}
        if {r = 0} a gcd_(r a)

define-macro my-gcd()
    apply gcd_ (args) 2
Обратите внимание, как синтаксис совместим с макросами, что было проблемой с предыдущими проектами , которые намеревались улучшить синтаксис Lisp (как описано Уилером и Глорией). Поскольку это просто сахар, конечная форма каждого нового выражения-это s-выражение, преобразованное читателем языка перед обработкой макросов-так что макросы не нуждаются в особом обращении. Таким образом, проект" читаемый Lisp " сохраняет гомоиконичность, свойство, которое позволяет Lisp представлять код как данные в языке, что позволяет ему быть мощной средой метапрограммирования.

Вам не придется ничем жертвовать. существует очень тщательно продуманный подход Дэвида Уилера , который полностью прозрачен и обратно совместим с полной поддержкой макросов и т. д.

У вас была бы Mathematica. Mathematica принимает вызовы функций как f[x, y, z], но при дальнейшем исследовании вы обнаружите, что f[x, y, z] на самом деле является синтаксическим сахаром для списка, в котором Head (элемент 0) является f и Rest (элементы от 1 до N) - это {x, y, z}. Вы можете создавать вызовы функций из списков, которые очень похожи на S-выражения, и вы можете разложить ненулевые функции в списки (Hold предотвращает оценку, подобно quote в Шепелявить).

Возможно, существуют семантические различия между Mathematica и Lisp / Scheme / Clojure, но синтаксис Mathematica-это демонстрация того, что вы можете переместить левую скобку на один атом и по-прежнему толковать ее разумно, строить код с помощью макросов и т. д. Синтаксис довольно легко преобразовать с помощью препроцессора (гораздо проще, чем семантику). Вы, вероятно, могли бы получить синтаксис, который вы хотите, через некоторые умные подклассы LispReader Clojure. Есть даже a проект , который стремится решить отталкивающие скобки Клоджюра, заменив их все квадратными скобками. (Меня поражает, что это считается большой проблемой.)

Я использовал код C / C# / Java / Pascal, поэтому я подчеркиваю с чувством, что Lisp-код немного чужд. Однако это чувство длится всего несколько недель - через довольно короткое время стиль Lisp будет чувствовать себя очень естественно, и вы начнете ругать другие языки за их "неправильный" синтаксис : -)

Существует очень хорошая причина для синтаксиса Lisp. Ведущие скобки делают код логически проще для анализа и чтения, собирая как функцию, так и выражения, которые составляют ее аргументы в единой форме.

И когда вы манипулируете кодом / используете макросы, именно эти формы имеют значение: это строительные блоки всего вашего кода. Поэтому принципиально имеет смысл поставить скобки в таком месте, которое точно разграничивает эти формы, а не произвольно оставлять первый элемент вне формы.

Философия" код-это данные " - это то, что делает возможным надежное метапрограммирование. Сравните с Perl / Ruby, которые имеют сложный синтаксис, их подходы к метапрограммированию надежны только в очень ограниченных обстоятельствах. Лисп-метапрограммирование настолько надежно, что от него зависит ядро языка. Причина этого-единый синтаксис, общий для кода и данных (свойство гомоиконичности). S-выражения - это способ реализации этой однородности.

Что сказано, в Clojure есть обстоятельства, при которых возможна подразумеваемая скобка:

Например, следующие три выражения эквивалентны:

  1. (первый (отдых (Отдых [1 2 3 4 5 6 7 8 9])))
  2. (-> [1 2 3 4 5 6 7 8 9] (отдых) (отдых) (первый))
  3. (-> [1 2 3 4 5 6 7 8 9] отдых сначала отдых)

Обратите внимание, что в третьем макро -> способен в этом контексте выводить скобки и тем самым оставлять их. Существует много специальных сценариев, подобных этому. В дизайн генерала Клоджюра ошибается в сторону меньшего количества скобок. См., например, спорное решение об исключении скобок в cond. Клоджюр очень принципиален и последователен в своем выборе.

Достаточно интересно - существует альтернативный синтаксис ракетки:

@foo{blah blah blah}

Читается как

(foo "blah blah blah")
Were Clojure to go down this path - what would it have to sacrifice to get there?

Жертва будет чувством / ментально-модальным написанием кода путем создания списка списка списка.. или более технически "писать АСТ напрямую".

Примечание: есть и другие вещи, которые будут скарифицированы, как упоминалось в других ответах.