Поиск…


замечания

Это простая функция hello world в Common Lisp. Примеры напечатают текст Hello, World! (без кавычек, за которым следует новая строка) до стандартного вывода.

Common Lisp - это язык программирования, который в основном используется интерактивно с использованием интерфейса, известного как REPL. REPL (Read Eval Print Loop) позволяет вводить код, оценивать (запускать) и сразу видеть результаты. Запрос для REPL (в какой момент один из них вводит код, который должен быть запущен) обозначается CL-USER> . Иногда перед > должен появляться нечто иное, кроме CL-USER , но это все еще REPL.

После запроса появляется код, обычно либо одно слово (то есть имя переменной), либо форма (список слов / форм, заключенных между ( и ) ) (т. Е. Вызов функции или объявление и т. Д.). На следующей строке будет любой вывод, который программа печатает (или ничего, если программа ничего не печатает), а затем значения, возвращаемые путем вычисления выражения. Обычно выражение возвращает одно значение, но если оно возвращает несколько значений, они появляются один раз в строке.

Версии

Версия Дата выхода
Общий Лисп 1984-01-01
ANSI Common Lisp 1994-01-01

Привет, мир

Ниже следует отрывок из сеанса REPL с Common Lisp, в котором «Hello, World!» функция определена и выполнена. См. Замечания в нижней части этой страницы для более подробного описания REPL.

CL-USER> (defun hello ()
           (format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> 

Это определяет «функцию» нулевых аргументов с именем hello , которая будет писать строку "Hello, World!" за которым следует новая строка для стандартного вывода и возвращаем NIL .

Чтобы определить функцию, напишем

(defun name (parameters...)
  code...)

В этом случае функция называется hello , не принимает никаких параметров, а код, который он запускает, - это один вызов функции. Возвращаемое значение из функции lisp - это последний бит кода в функции для запуска, так что hello возвращается (format t "Hello, World!~%") возвращается (format t "Hello, World!~%") .

В lisp для вызова функции write (function-name arguments...) где function-name - это имя функции, а arguments... - это список аргументов (разделенных пробелами) для вызова. Существуют некоторые особые случаи, которые выглядят как вызовы функций, но не являются, например, в приведенном выше коде не существует функции defun , вызываемой, она обрабатывается специально и определяет функцию вместо этого.

Во втором приглашении REPL, после того как мы определили функцию hello , мы вызываем его без параметров, записывая (hello) . Это, в свою очередь, вызовет функцию format с параметрами t и "Hello, World!~%" . Функция format производит форматированный вывод на основе аргументов, которые он задает (немного похож на расширенную версию printf в C). Первый аргумент указывает, куда выводить, с t значением standard-output. Второй аргумент говорит, что печатать (и как интерпретировать любые дополнительные параметры). Директива (специальный код во втором аргументе) ~% сообщает формату печати новой строки (т.е. в UNIX она может писать \n и на windows \r\n ). Формат обычно возвращает NIL (немного как NULL на других языках).

После второго запроса мы видим, что Hello, World был напечатан, а на следующей строке возвращаемое значение было NIL .

Привет, Имя

Это немного более продвинутый пример, который показывает еще несколько функций общего lisp. Начнем с простого Hello, World! функции и продемонстрировать некоторые интерактивные разработки на REPL. Обратите внимание, что любой текст из точки с запятой ; , остальная часть строки - комментарий.

CL-USER> (defun hello ()
       (format t "Hello, World!~%")) ;We start as before
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (defun hello-name (name) ;A function to say hello to anyone
       (format t "Hello, ~a~%" name)) ;~a prints the next argument to format
HELLO-NAME
CL-USER> (hello-name "Jack")
Hello, Jack
NIL
CL-USER> (hello-name "jack") ;doesn't capitalise names
Hello, jack
NIL
CL-USER> (defun hello-name (name) ;format has a feature to convert to title case
       (format t "Hello, ~:(~a~)~%" name)) ;anything between ~:( and ~) gets it
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack")
Hello, Jack
NIL
CL-USER> (defun hello-name (name)
       (format t "Hello, ~:(~a~)!~%" name))
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack") ;now this works
Hello, Jack!
NIL
CL-USER> (defun hello (&optional (name "world")) ;we can take an optional argument
       (hello-name name)) ;name defaults to "world"
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (hello "jack")
Hello, Jack!
NIL
CL-USER> (hello "john doe") ;note that this capitalises both names
Hello, John Doe!
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~a ~r" name number)) ;~r prints a number in English
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;this doesn't quite work
Hello, Louis sixteen
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~:(~a ~:r~)!" name number)) ;~:r prints an ordinal
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Sixteenth!
NIL
CL-USER> (defun hello-person (name &key (number))
       (format t "Hello, ~:(~a ~@r~)!" name number)) ;~@r prints Roman numerals
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Xvi!
NIL
CL-USER> (defun hello-person (name &key (number)) ;capitalisation was wrong
       (format t "Hello, ~:(~a~) ~:@r!" name number))
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;thats better
Hello, Louis XVI!
NIL
CL-USER> (hello-person "Louis") ;we get an error because NIL is not a number
Hello, Louis ; Evaluation aborted on #<SB-FORMAT:FORMAT-ERROR {1006641AB3}>.
CL-USER> (defun say-person (name &key (number 1 number-p)
                                      (title nil) (roman-number t))
       (let ((number (if number-p
                 (typecase number
                   (integer
                (format nil (if roman-number " ~:@r" " ~:(~:r~)") number))
                   (otherwise
                (format nil " ~:(~a~)" number)))
                 "")) ; here we define a variable called number
         (title (if title 
                (format nil "~:(~a~) " title)
                ""))) ; and here one called title
         (format nil "~a~:(~a~)~a" title name number))) ;we use them here

SAY-PERSON
CL-USER> (say-person "John") ;some examples
"John"
CL-USER> (say-person "john doe")
"John Doe"
CL-USER> (say-person "john doe" :number "JR")
"John Doe Jr"
CL-USER> (say-person "john doe" :number "Junior")
"John Doe Junior"
CL-USER> (say-person "john doe" :number 1)
"John Doe I"
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;this is wrong
"John Doe First"
CL-USER> (defun say-person (name &key (number 1 number-p)
                                      (title nil) (roman-number t))
       (let ((number (if number-p
                 (typecase number
                   (integer
                (format nil (if roman-number " ~:@r" " the ~:(~:r~)") number))
                   (otherwise
                (format nil " ~:(~a~)" number)))
                 ""))
         (title (if title 
                (format nil "~:(~a~) " title)
                "")))
         (format nil "~a~:(~a~)~a" title name number)))
WARNING: redefining COMMON-LISP-USER::SAY-PERSON in DEFUN
SAY-PERSON
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;thats better
"John Doe the First"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number nil)
"King Louis the Sixteenth"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number t)
"King Louis XVI"
CL-USER> (defun hello (&optional (name "World") &rest arguments) ;now we will just
       (apply #'hello-name name arguments)) ;pass all arguments to hello-name
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (defun hello-name (name &rest arguments) ;which will now just use
       (format t "Hello, ~a!" (apply #'say-person name arguments))) ;say-person
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello "louis" :title "king" :number 16) ;this works now
Hello, King Louis XVI!
NIL
CL-USER>

Это освещает некоторые дополнительные функции функции format Common Lisp, а также некоторые функции, такие как необязательные параметры и аргументы ключевых слов (например, :number ). Это также дает пример интерактивной разработки в REPL в общем lisp.

Простая программа Hello World в REPL

Common Lisp REPL - это интерактивная среда. Каждая форма, написанная после запроса, оценивается, и ее значение впоследствии печатается в результате оценки. Итак, самая простая программа Hello, World! В Common Lisp:

CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>

Что происходит здесь, так это то, что строковый costant задается во вводе REPL, он вычисляется и результат печатается. Из этого примера видно, что строки, такие как числа, специальные символы, такие как NIL и T и несколько других литералов, являются самооценками : они сами оценивают.

Основные выражения

Попробуем некоторое базовое выражение в REPL:

CL-USER> (+ 1 2 3)
6
CL-USER> (- 3 1 1)
1
CL-USER> (- 3)
-3
CL-USER> (+ 5.3 (- 3 2) (* 2 2))
10.3
CL-USER> (concatenate 'string "Hello, " "World!")
"Hello, World!"
CL-USER> 

Основной строительный блок Common Lisp - это форма . В этих примерах мы имеем формы функций , то есть выражения, написанные как список, в которых первый элемент является оператором (или функцией), а остальные элементы являются операндами (это называется «Префиксная нотация» или «Польская нотация» «). Написание форм в REPL вызывает их оценку. В примерах вы можете увидеть простые выражения, аргументы которых являются постоянными числами, строками и символами (в случае 'string , которая является именем типа). Вы также можете видеть, что арифметические операторы могут принимать любое количество аргументов.

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

(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...

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

Сумма списка целых чисел

(defun sum-list-integers (list)
    (reduce '+ list))

; 10
(sum-list-integers '(1 2 3 4))

; 55
(sum-list-integers '(1 2 3 4 5 6 7 8 9 10))

Лямбда-выражения и анонимные функции

Анонимная функция может быть определена без имени через выражение Lambda . Для определения этих типов функций вместо ключевого слова defun используется ключевое слово lambda . Следующие строки эквивалентны и определяют анонимные функции, которые выводят сумму двух чисел:

(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))

Их полезность заметна при создании Лямбда-форм , то есть в форме, которая представляет собой список, в котором первым элементом является лямбда-выражение, а остальные элементы являются аргументами анонимной функции. Примеры ( онлайн-исполнение ):

(print ((lambda (x y) (+ x y)) 1 2)) ; >> 3

(print (mapcar (lambda (x y) (+ x y)) '(1 2 3) '(2 -5 0))) ; >> (3 -3 3)

Общие учебные ресурсы Lisp

Интернет-книги

Это книги, которые свободно доступны в Интернете.

Интернет-ссылки

  • Common Lisp Hyperspec - это справочный документ для Common Lisp.
  • Common Lisp Cookbook - это список полезных рецептов Lisp. Также содержит список других онлайн-источников информации CL.
  • В Common Lisp Quick Reference есть листы для печати Lisp.
  • Lispdoc.com ищет несколько источников информации о Lisp (Practical Common Lisp, Successful Lisp, On Lisp, HyperSpec) для документации.
  • L1sp.org - это служба переадресации для документации.

Не в сети

Это книги, которые вам, вероятно, придется купить или получить в библиотеке.

Интернет-сообщества

Библиотеки

  • Quicklisp является библиотечным менеджером для Common Lisp и имеет длинный список поддерживаемых библиотек .
  • QuickDocs размещает библиотечную документацию для многих библиотек CL.
  • Awesome CL - это кураторский список библиотек, фреймворков и других блестящих материалов, отсортированных по категориям.

Предварительно упакованные среды Lisp

Это среды редактирования Lisp, которые легко установить и начать работу, потому что все, что вам нужно, предварительно упаковано и предварительно настроено.

  • Portacle - это переносная и многоплатформенная среда Common Lisp. Он отправляет слегка настроенные Emacs со Slime, SBCL (популярная реализация Common Lisp), Quicklisp и Git. Никакой установки не требуется, так что это очень быстрый и простой способ добиться успеха.
  • Lispbox - это среда IDE (Emacs + SLIME), Common Lisp (Clozure Common Lisp) и менеджер библиотек (Quicklisp), предварительно упакованные в виде архивов для Windows, Mac OSX и Linux. Потомок «Лиспа в коробке», рекомендованный в книге «Практические общие Лиспы».
  • Не предварительно упакован, но SLIME превращает Emacs в общую среду Lisp IDE и содержит руководство пользователя, которое поможет вам начать работу. Требуется отдельная реализация Common Lisp.

Общие реализации Lisp

В этом разделе перечислены некоторые общие реализации CL и их руководства. Если не указано иное, это реализация программного обеспечения. См. Также список бесплатных программ Clic's Common Lisp и список коммерческих реализаций Common Lisp в Википедии .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow