Введение в Lisp

Помечено: 

В этой теме 2 ответа, 3 участника, последнее обновление  oldrat984 10 мес., 3 нед. назад.

Просмотр 3 сообщений - с 1 по 3 (из 3 всего)
  • Автор
    Сообщения
  • #3858

    dimazilla
    Участник

    Статья не моя, она безвозмездно предоставлена мне Евтушенко Дмитрием. За что я ему очень благодарен. Прошу строго не судить, вероятно, это «проба пера».

    Суть Lisp

    Lisp — не только один из древнейших языков программирования, а так же первый функциональны язык программирования.

    Язык лисп не существует. Существуют различные диалекты лиспа. Диалекты лиспа отличаются только структурой базовых функций (например вывод в Common Lisp (print что-то), а в Scheme (display что-то)). В дальнейшем мы будем писать на Common Lisp и Scheme.

    Списки — наше все

    Лисп работает на списках. Программа, написанная на лиспе, представляет из себя ряд списков. Списки представляются ввиде скобок, в которые через пробел вписаны элементы списка. Например, (1 2 3). Элементами списка могут быть как другие списки, так и атомы — числа, название переменных/функций и т.д.

    Рассмотрим, как интерпретатор лиспа анализирует следующий список:
    (+ 2 2)

    Шайтан машина берет первый элемент и проверяет, является ли он функцией. Остальные элементы являются аргументами функции. Таким образом, выражение вернет 4. Подобные выражения называются S-выражениями. Если какие-либо элементы списка являются S-выражениями, то они тоже будут вычислены. Например (+ 2 (* 2 2)) вернет 6.

    Передать аргумент в виде списка можно двумя способами: использовать функции quote или list. Первая просто вернет свой аргумент в чистом виде,
    вторая предварительно вычислит свои аргументы:

    (quote ((+ 1 2) (* 1 2))) -> ((+ 1 2) (* 1 2))
    (list (+ 1 2) (* 1 2)) -> (3 2)

    Крылья, перья. . . Главное — хвост

    Настало время познакомиться со структурой списка. Наберите в своем интерпритаторе (cons 1 2). Он вернет вам (1 . 2). Это cons-ячейка. Наберите (car (cons 1 2)) и (cdr (cons 1 2)). Эти команды вернут 1 и 2 соответственно.

    Применим car и cdr к списку (1 2 3):
    (car (1 2 3)) -> 1
    (cdr (1 2 3)) -> (2 3)

    Вывод: список является связкой нескольких cons-ячеек. Первый элемент называется головой, оставшиеся — хвостом. Хвост всегда оканчивается пустым списком.

    #3869

    Хорошее начало, но мне кажется, что новичок зайдет, увидит «какие-то» списки, испугается и убежит. Есть предложение добавить (подумаем куда вставить) примеры. Начать можно с «hello world» и какой-нибудь простой игры типа «угадай число». Как смотрите на это?

    #4220

    oldrat984
    Участник

    На самом деле в том топике всё неправильно:
    как минимум:
    во-первых: quote — не функция в терминалогии лиспа, а «специальная форма»,
    во-вторых: лиспы отличаются между собой не только «структурой базовых функций», а порою много чем, например макро-системой, набором встроенных специальных форм, или «организацией» модульности, или, например, вообще синтаксисом (если взять например scheme, common lisp, clojure и emacs lisp, то у всех у них немножко отличается «reader» (в common lisp и в некоторых scheme-ах (по крайней мере в racket есть способ), он программируемый)), ну и: функциональность большинства диалектов лиспа под большим вопросом (например в common lisp половина функций не чистые, есть goto (причём и лексический, и динамический), есть присваивания (причём обобщённые), да и вообще side-эффекты вообщем-то никак не «локализуются» (в отличии от того же Haskell-я, например)).

    Ну это я так для справки. (Конечно это всё очень сложно как-то описать в 10 предложениях, но в результате, то что написано в топике выглядит не правдой, и не очень убедительно).

    P.S. пожалуй единственное, в чём проявляется «функциональность» лиспа (по крайней мере common lisp) это
    первое: «first-class functions», и может быть то, что любое выражение, возвращает значение (на самом деле не совсем так) и второе: более менее «можно подставить что угодно куда угодно» в смысле нет деления на statement и expression,
    так что можно написать например (+ (if nil 2 3) 4) и лисп вполне себе выдаст 7 несмотря на то, ‘+’ это обычная функция, а ‘if’ это специальная форма.

    Причём конкретно в common lisp порядок вычисления аргументов функции вполне определён (слева на право), поэтому можно (хотя наверное не нужно) вообще писать аргументы с побочными эффектами.
    Что-то типа: (let ((tmp 1)) (+ (incf tmp) tmp)) всегда будет выдавать 4.

Просмотр 3 сообщений - с 1 по 3 (из 3 всего)

Для ответа в этой теме необходимо авторизоваться.