Lisp: список vs S-expression

Сейчас я изучаю Lisp. Я столкнулся с двумя терминами "список" и "S-выражение". Я просто не могу различить их. Являются ли они просто синонимами в Lisp?

Ответы

Ответ 1

Во-первых, не все S-выражения представляют списки; выражение, такое как foobar, представляющее голодный атом, также считается S-выражением. Как и синтаксис "cons cell", (car . cons), используется, когда часть "cons" сама по себе не является другим списком (или nil). Более знакомое выражение списка, например (a b c d), является просто синтаксическим сахаром для цепочки вложенных cons-ячеек; этот пример расширяется до (a . (b . (c . (d . nil)))).

Во-вторых, термин "S-выражение" относится к синтаксису - (items like this (possibly nested)). Такое S-выражение представляет собой представление в исходном коде Lisp списка, но оно не является технически самым списком. Это различие является таким же, как между последовательностью десятичных цифр и их числовым значением, или между последовательностью символов в кавычках и результирующей строкой.

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

Например, рассмотрим это выражение:

(+ 1 2)

Вышеприведенное является прямым S-выражением, которое представляет собой плоский список, состоящий из атомов +, 1 и 2.

Однако в программе Lisp такой список будет интерпретироваться как вызов функции + с 1 и 2 в качестве аргументов. (Имейте в виду, что это список, а не S-выражение, которое интерпретируется так: оценщик передается спискам, которые были предварительно проанализированы читателем, а не текстом исходного кода.)

Итак, в то время как вышеприведенное S-выражение представляет список, его редко упоминает как "список" в контексте программы Lisp. Если не обсуждать макросы или внутреннюю работу читателя или заниматься метасинтетическим обсуждением из-за другого контекста генерации кода или синтаксического анализа, типичный программист Lisp вместо этого рассмотрит вышеуказанное как числовое выражение.

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

'(+ 1 2)
(quote (+ 1 2))
(list '+ 1 2)

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

Ответ 2

S-выражения - это обозначения для данных.

Исторически s-выражение (сокращенное для символического выражения) описывается как:

  • символы, такие как FOO и BAR
  • cons ячейки с s-выражениями в качестве первого и второго элементов: ( выражение-1 . выражение-2 )
  • символ завершения списка NIL
  • и соглашение для записи списков: ( A . ( B . NIL ) ) проще записать в виде списка (A B)

Обратите внимание также, что исторически текст программы был написан по-разному. Пример для функции ASSOC.

assoc[x;y] =
   eq[caar[y];x] -> cadar[y];
   T -> assoc[x;cdr[y]]

Исторически существовало также отображение из этих m-выражений (краткое для мета-выражений) в s-выражения. Сегодня большинство Lisp программных кодов написано с использованием s-выражений.

Это описано здесь: Маккарти, рекурсивные функции символических выражений

В языке программирования Lisp, таком как Common Lisp, s-выражения в настоящее время имеют больше синтаксиса и могут кодировать больше типов данных:

  • Символы: symbol123, |This is a symbol with spaces|
  • Числа: 123, 1.0, 1/3,...
  • Строки: "This is a string"
  • Символы: #\a, #\space
  • Векторы: #(a b c)
  • Концы и списки: ( a . b ), (a b c)
  • Комментарии: ; this is a comment, #| this is a comment |#

и более.

Списки

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

Боковое примечание: программы и формы

На языке программирования, таком как Common Lisp, выражения языка программирования не являются текстовыми, а данными! Это отличается от многих других языков программирования. Выражения на языке программирования Common Lisp называются Lisp forms.

Например, вызов функции - это Lisp data, где вызов представляет собой список с символом функции в качестве его первого элемента, а следующие элементы - его аргументы.

Мы можем написать это как (sin 3.0). Но это действительно данные. Данные, которые мы также можем построить.

Функция для оценки форм Lisp называется EVAL и принимает данные Lisp, а не текст программы или строки текста программы. Таким образом, вы можете создавать программы, используя Lisp функции, возвращающие данные Lisp: (EVAL (LIST 'SIN 3.0)) оценивается до 0.14112.

Так как формы Lisp имеют представление данных, они обычно записываются с использованием внешнего представления данных Lisp - что это? - s-выражения!

Это s-выражения. Lisp формы как Lisp данные записываются внешне как s-выражение.

Ответ 3

Вы должны сначала понять главную функцию Lisp - программа может управляться как данные. В отличие от других языков (например, C или Java), где вы пишете программу с помощью специального синтаксиса ({, }, class, define и т.д.), В Lisp вы пишете код как (вложенный) list (btw, это позволяет напрямую выражать абстрактные синтаксические деревья). Еще раз: вы пишете программы, которые выглядят так же, как структуры данных языка.

Когда вы говорите об этом как данные, вы называете его "list" , но когда вы говорите о программном коде, вам лучше используйте термин "s-expression" . Таким образом, технически они похожи, но используются в разных контекстах. Единственным реальным местом, где эти термины являются смешанными, является метапрограммирование (обычно с макросами).

Также обратите внимание, что s-expression может также состоять только из atom (например, числа, строки и т.д.).

Ответ 4

Простым определением для S-выражения является

(define S-expression?
    (λ (object)
        (or (atom? object) (list? object))))

;; Where atom? is:

(define atom?
  (λ (object) 
    (and (not (pair? object)) (not (null? object)))))

;; And list? is:

(define list? (λ (object)
  (let loop ((l1 object) (l2 object))
    (if (pair? l1)
        (let ((l1 (cdr l1)))
          (cond ((eq? l1 l2) #f)
                ((pair? l1) (loop (cdr l1) (cdr l2)))
                (else (null? l1))))
        (null? l1)))))

Ответ 5

Оба написаны аналогичным образом: (бла-бла-бла), могут быть вложенными. с одним отличием - списки имеют префикс с апострофом.

Об оценке:

  • S-выражение возвращает некоторый результат (может быть атом или список или нуль или что-то еще)
  • Списки возврата Списки

Если нам нужно, мы можем конвертировать списки в s-exp и наоборот.

  • (eval '(blah blah blah)) = > рассматривается как s-exp и возвращается результат.
  • (quote (blah blah blah)) = > sexp преобразуется в список, и список возвращается без оценки

МСФО:

  • Если список обрабатывается как данные, он называется List, если он рассматривается как код, он называется s-exp.