Сега уча Lisp. Срещнах 2 термина "списък" и "S-израз". Просто не мога да ги различа. Дали са само синоними в Lisp?
Lisp: списък срещу S-израз
Отговори (5)
Първо, не всички S-изрази представляват списъци; израз като foobar
, представляващ гол атом, също се счита за S-израз. Както и синтаксисът "против клетка", (car . cons)
, използван, когато частта "против" сама по себе си не е друг списък (или нула). По-познатият списъчен израз, като (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-говор.
eval
.
- person Will Ness; 02.10.2016
S-изразите са нотация за данни.
Исторически s-израз (съкратено от символичен израз) се описва като:
- символи като
FOO
иBAR
- против клетки със 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-изрази.
Това е описано тук: McCarthy, Recursive Functions of Symbolic Expressions
В език за програмиране 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 |#
и още.
Списъци
Списъкът е структура от данни. Състои се от клетки с минуси и маркер за край на списъка. Списъците имат в Lisp нотация като списъци в s-изрази. Можете да използвате някои други обозначения за списъци, но в Lisp човек се е спрял на синтаксиса на s-израз, за да ги напише.
Странична бележка: програми и формуляри
В език за програмиране като Common Lisp, изразите на езика за програмиране не са текст, а данни! Това е различно от много други езици за програмиране. Изразите в езика за програмиране Common Lisp се наричат Lisp forms
.
Например извикването на функция е Lisp данни, където извикването е списък с функционален символ като негов първи елемент, а следващите елементи са неговите аргументи.
Можем да запишем това като (sin 3.0)
. Но това наистина са данни. Данни, които също можем да конструираме.
Функцията за оценяване на Lisp форми се нарича EVAL
и взема Lisp данни, а не програмен текст или низове от програмен текст. По този начин можете да създавате програми, използвайки Lisp функции, които връщат Lisp данни: (EVAL (LIST 'SIN 3.0))
оценява на 0.14112
.
Тъй като формите на Lisp имат представяне на данни, те обикновено се пишат с помощта на външно представяне на данни на Lisp - което е какво? - s-изрази!
Това са s-изрази. Формите на Lisp като данни на Lisp се записват външно като s-израз.
Първо трябва да разберете основната функция на Lisp - програмата може да се манипулира като данни. За разлика от други езици (като C или Java), където пишете програма, като използвате специален синтаксис ({
, }
, class
, define
и т.н.), в Lisp пишете код като (вложени) списъци (между другото, това позволява да изразите абстрактни синтактични дървета директно). Още веднъж: пишете програми, които изглеждат точно като структурите от данни на езика.
Когато говорите за това като данни, вие го наричате "списък", но когато говорите за програмен код, трябва по-добре да използвате термина < strong>"s-израз". Следователно технически те са сходни, но се използват в различен контекст. Единственото реално място, където тези термини се смесват, е мета-програмирането (обикновено с макроси).
Също така имайте предвид, че s-изразът може също да се състои от единствения атом (като числа, низове и т.н.).
eval
не работи с низове; в това тя е различна от функцията със същото име в повечето съвременни динамични езици. Вместо това, той очаква неговият аргумент вече да е представянето на кода в паметта, което е (дърво от йерархично вложени) списъци. Четецът трансформира S-изрази в списъци, които трябва да бъдат оценени. И така, S-изрази: текстово представяне на списъци. Сериализирани, наистина, по същия начин, по който JSON или XML могат да представят дърво на обекти.
- person Mark Reed; 30.05.2012
Една проста дефиниция за 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)))))
И двете се изписват по подобен начин: (бла-бла-бла), може да бъде вложено. с една разлика - списъците са с представка апостроф.
При оценка:
- S-изразът връща някакъв резултат (може да е атом, списък, нула или нещо друго)
- Списъци връщат списъци
Ако имаме нужда, можем да конвертираме списъци в s-exp и обратно.
- (eval '(blah blah blah)) => списъкът се третира като s-exp и се връща резултат.
- (quote (blah blah blah)) => sexp се преобразува в списък и списъкът се връща без оценка
IAS:
- Ако списъкът се третира като данни, той се нарича Списък, ако се третира като код, се нарича s-exp.
s-expression
е запазен за говорене конкретно за синтаксиса по метатекстуален начин.
- person Mark Reed; 30.05.2012