Практический пример гибкости Lisp? [закрытый]

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

67
задан Peter Mortensen 24 November 2013 в 11:54
поделиться

18 ответов

Мне нравятся макросы.

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

Некоторые люди смущены по поводу воображаемого штрафа во время выполнения макросов, таким образом, я добавил попытку разъяснения вещей в конце.

В Начале, Было Дублирование

(defun ldap-users ()
  (let ((people (make-hash-table :test 'equal)))
    (ldap:dosearch (ent (ldap:search *ldap* "(&(telephonenumber=*) (cn=*))"))
                   (let ((mail  (car (ldap:attr-value ent 'mail)))
                         (uid   (car (ldap:attr-value ent 'uid)))
                         (name  (car (ldap:attr-value ent 'cn)))
                         (phonenumber (car (ldap:attr-value ent 'telephonenumber))))
                      (setf (gethash uid people)
                            (list mail name phonenumber))))
    people))

, можно думать о "привязке, которой позволяют", как о локальной переменной, которая исчезает вне формы, которой ПОЗВОЛЯЮТ. Заметьте форму привязки - они очень похожи, отличаясь только по атрибуту объекта LDAP и имени ("локальная переменная") для привязки значения с. Полезный, но немного подробный и содержит дублирование.

На Quest для Красоты

Теперь, не было бы хорошо, если бы у нас не должно было быть всего того дублирования? Общая идиома, С-... макросы, которые связывают значения на основе выражения, от которого можно захватить значения. Давайте представим наш собственный макрос, который работает как этот, WITH-LDAP-ATTRS, и замените его в нашем исходном коде.

(defun ldap-users ()
  (let ((people (make-hash-table :test 'equal))) ; equal so strings compare equal!
    (ldap:dosearch (ent (ldap:search *ldap* "(&(telephonenumber=*) (cn=*))"))
                   (with-ldap-attrs (mail uid name phonenumber) ent
                       (setf (gethash uid people)
                             (list mail name phonenumber))))
    people))

Вы видели, как набор строк внезапно исчез и был заменен всего одной одной строкой? Как сделать это? Используя макросы, конечно - код, который пишет код! Макросы в Lisp являются полностью различным животным, чем те, можно найти в C/C++ с помощью препроцессора: здесь, можно работать реальный код Lisp (не #define пух в cpp), который генерирует код Lisp, прежде чем другой код будет скомпилирован. Макросы могут использовать любой реальный код Lisp, т.е. обычные функции. По существу никакие пределы.

Избавление от Ужасных

Так, давайте посмотрим, как это было сделано. Для замены одного атрибута мы определяем функцию.

(defun ldap-attr (entity attr)
  `(,attr (car (ldap:attr-value ,entity ',attr))))

синтаксис одинарной левой кавычки выглядит немного волосатым, но что он делает легко. При вызове LDAP-ATTRS он выложит список, который содержит значение из [1 111] (это - запятая), сопровождаемый [1 112] ("первый элемент в списке" (пара недостатков, на самом деле), и существует на самом деле функция, вызванная first, можно использовать, также), который получает первое значение в списке, возвращенном [1 114]. Поскольку это не код, который мы хотим выполнить, когда мы компилируем код (получение значений атрибута - то, что мы хотим сделать, когда мы работаем программа), мы не добавляем запятую перед вызовом.

Так или иначе. Прохождение, к остальной части макроса.

(defmacro with-ldap-attrs (attrs ent &rest body)
  `(let ,(loop for attr in attrs
         collecting `,(ldap-attr ent attr))
     ,@body)) 

,@ - синтаксис должен поместить содержание списка где-нибудь вместо фактического списка.

Результат

можно легко проверить, что это даст Вам правильную вещь. Макросы часто пишутся этот путь: Вы начинаетесь с кодом, который Вы хотите сделать более простым (вывод), что Вы хотите записать вместо этого (вход), и затем Вы начинаете прессовать макрос, пока Ваш вход не дает корректный вывод. Функция macroexpand-1 скажет Вам, если Ваш макрос будет корректен:

(macroexpand-1 '(with-ldap-attrs (mail phonenumber) ent
                  (format t "~a with ~a" mail phonenumber)))

оценивает к [1 147]

(let ((mail (car (trivial-ldap:attr-value ent 'mail)))
      (phonenumber (car (trivial-ldap:attr-value ent 'phonenumber))))
  (format t "~a with ~a" mail phonenumber))

, Если Вы сравните ПОЗВОЛЕННУЮ привязку расширенного макроса с кодом в начале, Вы найдете, что это находится в той же форме!

Время компиляции по сравнению со Временем выполнения: Макросы по сравнению с Функциями

макрос А является кодом, который достигнут в [1 127] время компиляции с добавленным скручиванием, что они могут назвать любой обычным функция или макрос, как им нравится! Это не намного больше, чем необычный фильтр, беря некоторые аргументы, применяя некоторые преобразования и затем подавая компилятор получающийся s-экспорт

В основном, это позволяет Вам записать свой код в глаголах, которые могут быть найдены в проблемной области вместо примитивов низкого уровня с языка! Как глупый пример, рассмотрите следующее (если when уже не было встроенное)::

(defmacro my-when (test &rest body)
  `(if ,test 
     (progn ,@body)))

if встроенный примитив, который только позволит Вам выполниться один форма в ответвлениях, и если Вы хотите иметь больше чем один, ну, в общем, необходимо использовать progn::

;; one form
(if (numberp 1)
  (print "yay, a number"))

;; two forms
(if (numberp 1)
  (progn
    (assert-world-is-sane t)
    (print "phew!"))))

С нашим новым другом, my-when, мы могли оба a) использовать более соответствующий глагол, если у нас нет ложного ответвления и b) добавить неявный оператор упорядочивания, т.е. progn::

(my-when (numberp 1)
  (assert-world-is-sane t)
  (print "phew!"))

скомпилированный код никогда не будет содержать my-when, тем не менее, потому что в первой передаче, все макросы расширены, таким образом, существует никакой штраф во время выполнения включено!

Lisp> (macroexpand-1 '(my-when (numberp 1)
                        (print "yay!")))

(if (numberp 1)
  (progn (print "yay!")))

Примечание, что macroexpand-1 только делает один уровень расширений; это возможно (скорее всего, на самом деле!), который расширение продолжает далее вниз. Однако в конечном счете Вы поразите определенные для компилятора детали реализации, которые часто не очень интересны. Но продолжение расширения результата в конечном счете или получит Вас больше деталей, или просто Ваш вход s-exp назад.

Hope, которая разъясняет вещи. Макросы являются мощным инструментом и одной из функций в Lisp, который я люблю.

77
ответ дан amn 24 November 2019 в 14:26
поделиться

John Ousterhout сделал это интересное наблюдение относительно Lisp в 1994:

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

, Если [язык] делает людей более продуктивными тогда, они будут использовать его; когда некоторый другой язык приходит, который лучше (или если это уже будет здесь), тогда люди переключатся на тот язык. Это - Закон, и это хорошо. В Законе говорится мне, что Схема (или любой другой диалект Lisp) является, вероятно, не "правильным" языком: слишком много людей голосовали их ногами за прошлые 30 лет.

http://www.vanderburg.org/OldPages/Tcl/war/0009.html

-1
ответ дан Mark Harrison 24 November 2019 в 14:26
поделиться

Очевидный факт, что это - язык мультипарадигмы, делает это очень очень гибким.

2
ответ дан temp2290 24 November 2019 в 14:26
поделиться

Вы могли бы найти это сообщение Eric Normand полезный. Он описывает, как, поскольку кодовая база растет, Lisp помогает, позволяя Вам создать язык до Вашего приложения. В то время как это часто прилагает дополнительные усилия вначале, они дают Вам большое преимущество позже.

2
ответ дан drewr 24 November 2019 в 14:26
поделиться

@Mark,

, В то время как существует некоторая истина к тому, что Вы говорите, я полагаю, что это не всегда как прямое.

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

Плюс Вы должны признать, что языки, которые имеют поддержку огромных коммерческих объектов, таких как Microsoft или Sun, будут всегда иметь преимущество на рынке по сравнению с языками без такой поддержки.

для ответа на исходный вопрос, Paul Graham пытается дать пример здесь даже при том, что я признаю, что это не обязательно как практично , поскольку я хотел бы:-)

4
ответ дан Pat 24 November 2019 в 14:26
поделиться

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

5
ответ дан Taryn 24 November 2019 в 14:26
поделиться

Одной вещью, которую я люблю, является то, что я могу обновить код "время выполнения", не теряя состояние приложения. Это - вещь, только полезная в некоторых случаях, но когда это полезно, уже имея его там (или, только для минимальной стоимости во время разработки) является НАМНОГО более дешевым, чем необходимость реализовать его с нуля. Тем более, что это прибывает в "нет почти ни к какой" стоимости.

6
ответ дан Vatine 24 November 2019 в 14:26
поделиться

Посмотрите, как Вы можете расширять язык Common LISP с помощью XML шаблонная обработка : cl-quasi-quote XML пример , страница ,

(babel:octets-to-string
 (with-output-to-sequence (*html-stream*)
   <div (constantAttribute 42
         someJavaScript `js-inline(print (+ 40 2))
         runtimeAttribute ,(concatenate 'string "&foo" "&bar"))
     <someRandomElement
       <someOther>>>))

 =>

 "<div constantAttribute=\"42\"
       someJavaScript=\"javascript: print((40 + 2))\"
       runtimeAttribute=\"&amp;foo&amp;bar\">
    <someRandomElement>
      <someOther/>
    </someRandomElement>
  </div>"

проекта Это - в основном то же самое как читатель обратной галочки Lisp (который является для списка квази заключением в кавычки), но это также работает на различные другие вещи как XML (установленный на специальном <> синтаксис), JavaScript (установленный на 'js-inline), и т.д.

Для прояснения это реализовано в пользовательская библиотека ! И это компилирует статический XML, JavaScript, и т.д. части в , UTF-8 закодировал литеральные массивы байтов, которые готовы быть записанными в сетевой поток. С простым , (запятая) можно возвратиться к шепелявости и чередоваться, время выполнения генерировало данные в литеральные массивы байтов.

Это не для слабонервных, но это - то, во что библиотека компилирует вышеупомянутое:

(progn
 (write-sequence
  #(60 100 105 118 32 99 111 110 115 116 97 110 116 65 116 116 114 105 98
    117 116 101 61 34 52 50 34 32 115 111 109 101 74 97 118 97 83 99 114
    105 112 116 61 34 106 97 118 97 115 99 114 105 112 116 58 32 112 114
    105 110 116 40 40 52 48 32 43 32 50 41 41 34 32 114 117 110 116 105
    109 101 65 116 116 114 105 98 117 116 101 61 34)
  *html-stream*)
 (write-quasi-quoted-binary
  (let ((*transformation*
          #<quasi-quoted-string-to-quasi-quoted-binary {1006321441}>))
    (transform-quasi-quoted-string-to-quasi-quoted-binary
      (let ((*transformation*
               #<quasi-quoted-xml-to-quasi-quoted-string {1006326E51}>))
        (locally
            (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
         (let ((it (concatenate 'string "runtime calculated: " "&foo" "&bar")))
           (if it
               (transform-quasi-quoted-xml-to-quasi-quoted-string/attribute-value it)
               nil))))))
  *html-stream*)
 (write-sequence
  #(34 62 10 32 32 60 115 111 109 101 82 97 110 100 111 109 69 108 101 109
    101 110 116 62 10 32 32 32 32 60 115 111 109 101 79 116 104 101 114 47
    62 10 32 32 60 47 115 111 109 101 82 97 110 100 111 109 69 108 101 109
    101 110 116 62 10 60 47 100 105 118 62 10)
  *html-stream*)
 +void+)

Для ссылки, два больших вектора байта в вышеупомянутом похожи на это, когда преобразовано в строку:

"<div constantAttribute=\"42\"
      someJavaScript=\"javascript: print((40 + 2))\"
      runtimeAttribute=\""

И второй:

"\">
 <someRandomElement>
    <someOther/>
  </someRandomElement>
</div>"

И это объединяется хорошо с другими структурами Lisp как макросы и функции. теперь, сравните это с JSPs...

7
ответ дан Peter Mortensen 24 November 2019 в 14:26
поделиться

Вещь, что мне нравятся больше всего о Lisp (и Smalltalk) системы, состоит в том, что они чувствуют себя живыми. Можно легко зондировать & измените системы Lisp, в то время как они работают.

, Если это звучит таинственным, запустите Emacs и введите некоторый код Lisp. Тип C-M-x и voilГ! Вы просто изменили Emacs из Emacs. Можно пойти и переопределить все функции Emacs, в то время как это работает.

Другая вещь состоит в том, что код = перечисляет эквивалентность, делают границу между кодом и данными очень тонкой. И благодаря макросам, очень легко расширить язык и сделать быстрым DSLs.

, Например, возможно кодировать основного разработчика HTML, с которым код очень близко к произведенному выводу HTML:

(html
  (head
    (title "The Title"))
  (body
    (h1 "The Headline" :class "headline")
    (p "Some text here" :id "content")))

=>

<html>
  <head>
    <title>The title</title>
  </head>
  <body>
    <h1 class="headline">The Headline</h1>
    <p id="contents">Some text here</p>
  </body>
</html>

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

8
ответ дан Peter Mortensen 24 November 2019 в 14:26
поделиться

Я нашел эту статью довольно интересной:

Сравнение Языка программирования: Lisp по сравнению с C++

автор статьи, Brandon Corfman, пишет об исследовании, которое сравнивает решения в Java, C++ и Lisp к проблеме программирования, и затем пишет его собственное решение в C++. Решением для сравнительного теста являются 45 строк Peter Norvig Lisp (записанный за 2 часа).

Corfman находит, что трудно уменьшить его решение меньше чем 142 строк C++ / STL. Его анализ почему, является интересным чтением.

9
ответ дан PoLáKoSz 24 November 2019 в 14:26
поделиться

Существует много уничтожающих функций в Lisp, но макросы являются тем, который я люблю particularily, потому что нет действительно барьера больше между тем, что определяет язык и что я определяю. Например, язык Common LISP не имеет в то время как конструкция. Я когда-то реализовал его в голове при обходе. Это просто и чисто:

(defmacro while (condition &body body)
  `(if ,condition
       (progn
         ,@body
         (do nil ((not ,condition))
           ,@body))))

И voilГ! Вы просто расширили язык языка Common LISP с помощью новой фундаментальной конструкции. Можно теперь сделать:

(let ((foo 5))
  (while (not (zerop (decf foo)))
    (format t "still not zero: ~a~%" foo)))

, Который распечатал бы:

still not zero: 4
still not zero: 3
still not zero: 2
still not zero: 1

Выполнение этого на любом языке не-Lisp оставляют как осуществление для читателя...

12
ответ дан Nowhere man 24 November 2019 в 14:26
поделиться

Мне нравится Система Объекта языка Common LISP (CLOS) и мультиметоды.

Большинство, если не все, языки объектно-ориентированного программирования имеют основные понятия классов и методов. Следующий отрывок в Python определяет классы PeelingTool и Овощ (что-то подобное Шаблону "посетитель"):

class PeelingTool:
    """I'm used to peel things. Mostly fruit, but anything peelable goes."""
    def peel(self, veggie):
        veggie.get_peeled(self)

class Veggie:
    """I'm a defenseless Veggie. I obey the get_peeled protocol
    used by the PeelingTool"""
    def get_peeled(self, tool):
        pass

class FingerTool(PeelingTool):
  ...

class KnifeTool(PeelingTool):
  ...

class Banana(Veggie):
    def get_peeled(self, tool):
        if type(tool) == FingerTool:
            self.hold_and_peel(tool)
        elif type(tool) == KnifeTool:
            self.cut_in_half(tool)

Вы помещаете peel метод в PeelingTool и имеете Банан, принимают его. Но, это должно принадлежать классу PeelingTool, таким образом, это может только использоваться, если у Вас есть экземпляр класса PeelingTool.

Версия системы Объекта языка Common LISP:

(defclass peeling-tool () ())
(defclass knife-tool (peeling-tool) ())
(defclass finger-tool (peeling-tool) ())

(defclass veggie () ())
(defclass banana (veggie) ())

(defgeneric peel (veggie tool)
  (:documentation "I peel veggies, or actually anything that wants to be peeled"))

;; It might be possible to peel any object using any tool,
;; but I have no idea how. Left as an exercise for the reader
(defmethod peel (veggie tool)
   ...)

;; Bananas are easy to peel with our fingers!
(defmethod peel ((veggie banana) (tool finger-tool))
  (with-hands (left-hand right-hand) *me*
    (hold-object left-hand banana)
    (peel-with-fingers right-hand tool banana)))

;; Slightly different using a knife
(defmethod peel ((veggie banana) (tool knife-tool))
  (with-hands (left-hand right-hand) *me*
    (hold-object left-hand banana)
    (cut-in-half tool banana)))

Что-либо может быть записано на любом языке, это полно по Тьюрингу; различие между языками - то, сколько обручей, до которых необходимо перейти, получает эквивалентный результат.

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

13
ответ дан Peter Mortensen 24 November 2019 в 14:26
поделиться

На самом деле хорошим практическим примером является Макрос ЦИКЛА Lisp.

http://www.ai.sri.com/pkarp/loop.html

макрос ЦИКЛА состоит просто в том что - макрос Lisp. Все же это в основном определяет мини-цикличное выполнение DSL (Предметно-ориентированный язык).

, Когда Вы просматриваете то небольшое учебное руководство, Вы видите (как раз когда новичок), что трудно знать, какая часть кода является частью макроса Цикла, и который является "нормальным" Lisp.

И это - один из ключевых компонентов, Шепелявит выразительность, что новый код действительно нельзя отличить от системы.

, В то время как в, скажем, Java, Вы не можете (сразу) быть в состоянии знать, какая часть программы прибывает из стандартной библиотеки Java по сравнению с Вашим собственным кодом, или даже сторонней библиотеки, Вы ДЕЙСТВИТЕЛЬНО знаете, какая часть кода является языком Java, а не просто вызовами метода на классах. Предоставленный, это - ВЕСЬ "язык Java", но как программист, Вы ограничены только выражением Вашего приложения как комбинация классов и методов (и теперь, аннотации). Принимая во внимание, что в Lisp, буквально все доступно для всех.

Полагают, что интерфейс Common SQL подключает язык Common LISP к SQL. Здесь, http://clsql.b9.com/manual/loop-tuples.html , они показывают, как макрос Цикла CL расширяется для создания SQL, связывающего "гражданина первого класса".

можно также наблюдать конструкции такой как" [выбор [имя] [фамилия]: от [сотрудника]: порядок - [фамилией]]". Это - часть пакета SQL CL и реализованный как "макрос читателя".

Видят, в Lisp, мало того, что можно сделать макросы для создания новых конструкций, как структуры данных, управляющие структуры, и т.д. Но можно даже изменить синтаксис языка посредством макроса читателя. Здесь, они используют макрос читателя (в случае,' [' символ) для заглядывания к режиму SQL, чтобы заставить SQL работать как встроенный SQL, а не как просто необработанные строки как на многих других языках.

Как разработчики приложений, наша задача состоит в том, чтобы преобразовать наши процессы и конструкции в к форме, которую может понять процессор. Это означает, что мы, неизбежно, должны "перекричать" на язык программирования, начиная с него "не понимает" нас.

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

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

13
ответ дан Will Hartung 24 November 2019 в 14:26
поделиться

Можно найти эту статью полезной: http://www.defmacro.org/ramblings/lisp.html

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

14
ответ дан Matthias Benkard 24 November 2019 в 14:26
поделиться

Лучшим примером, о котором я могу думать, который широко доступен, является книга Paul Graham, На Lisp. Полный PDF может быть загружен со ссылки, которую я просто дал. Вы могли также попробовать Практический язык Common LISP (также полностью имеющийся в сети).

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

18
ответ дан Jason Dagit 24 November 2019 в 14:26
поделиться

Я был студентом ИИ в Массачусетском технологическом институте в 1970-х годах. Как и любой другой студент, я думал, что язык имеет первостепенное значение. Тем не менее, Лисп был основным языком. Вот некоторые вещи, для которых я все еще думаю, что это довольно хорошо:

  • Символическая математика. Легко и поучительно написать символическое дифференцирование выражения и алгебраическое упрощение. Я все еще делаю это, даже если я делаю их на Си-независимо.

  • Доказательство теоремы. Время от времени я испытываю временные переживания ИИ, как будто пытаюсь доказать, что сортировка вставок верна. Для этого мне нужно сделать символические манипуляции, и я обычно прибегаю к Лиспу.

  • Маленькие доменно-специфические языки. Я знаю, что Лисп не действительно практично, но если я хочу опробовать небольшой DSL без необходимости разбираться с синтаксическим анализом и т. д., макросы Lisp облегчают его.

  • Алгоритмы небольшой игры, такие как поиск по минимаксному дереву игр, можно выполнить в как три строки.

  • Хотите попробовать лямбда-исчисление ? В Лиспе это легко.

Главным образом то, что Лисп делает для меня, - это умственные упражнения. Затем я могу перенести это на более практичные языки.

PS Говоря о лямбда-исчислении, то, что также началось в 1970-х годах, в той же самой AI-среде, заключалось в том, что ОО начал вторгаться в мозг каждого и каким-то образом интересоваться тем, чем оно ] , кажется, вытеснил большой интерес к тому, что хорошо для . Т.е. работа над машинным обучением, естественным языком, зрением, решением проблем - все это уходило в конец комнаты, в то время как занятия, сообщения, типы, полиморфизм,

7
ответ дан 24 November 2019 в 14:26
поделиться

Одна особенная вещь, которая меня впечатлила, - это возможность написать собственное расширение объектно-ориентированного программирования, если вам не нравится включенный CLOS.

Один из них находится в Garnet , а другой в On Lisp Пола Грэма.

Также есть пакет под названием Screamer , который позволяет недетерминированное программирование (которое я не знаю) не оценивается).

Любой язык, который позволяет вам изменять его для поддержки различных парадигм программирования, должен быть гибким.

4
ответ дан 24 November 2019 в 14:26
поделиться

Мне нравится этот пример макроса из http://common-lisp.net/cgi-bin/viewcvs.cgi/cl-selenium/?root=cl-selenium Это привязка Common Lisp к Selenium (среда тестирования веб-браузера), но вместо сопоставления каждого метода она считывает XML-документ определения API-интерфейса Selenium во время компиляции и генерирует код сопоставления с использованием макросов. Вы можете увидеть сгенерированный API здесь: common-lisp.net/project/cl-selenium/api/selenium-package/index.html

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

7
ответ дан 24 November 2019 в 14:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: