Точечная запись на схеме
Я новичок в программировании Scheme. Я знаю, что точечная запись в Схеме используется для представления пары символов, например '(a . b)
,
Первый элемент может быть символом или списком, это не имеет значения. Но особенно второй элемент должен быть символом, если это не так, может быть, например, список, то мы не можем создать пару со встроенным cons
процедура.
Так можно ли создать пару из 2 списков??? Ну, я думаю, что решение состоит в том, что преобразование списка в символ, но на самом деле это две совершенно разные вещи -> невозможно, как я понимаю.
Это код, который я написал:
(define compare-attrs
(lambda (attribute1 attribute2)
(if (or (and (null? attribute1) (null? attribute2)) (and (not (null? attribute1)) (not (null? attribute2))))
(cons attribute1 attribute2)
#f)))
В котором attribute1 и attribute2 - это 2 списка, и мой вывод:
attribute1 atrribute2
Ожидаемый результат: '(attribute1 . Attribute2)
Пожалуйста, объясните это. Заранее спасибо!!!
РЕДАКТИРОВАТЬ: добавление использования функции сравнения-атрибутов
Функция compare-attrs используется для извлечения части, которая описывает атрибуты сущностей и cons
их составить пару, сущности которых определены ниже:
(entity e0 (prov:label "entity e0")
(entity e1 (prov:location "London")
поэтому атрибут этих объектов (prov:label "entity e0")
а также (prov:location "London")
, Когда применяется функция compare-attrs, потому что эти атрибуты не являются null
так, чтобы результат, который я ожидаю, был
`(prov:label "entity e0") . (prov:location "London")`
3 ответа
Примечание: это каннибализируется из ответа на Рекурсивный диапазон в Лисп добавляет точку? , который действительно задает другой вопрос. Тем не менее, объяснение того, как пары печатаются, то же самое. В остальном ответ другой.
В вашем вопросе есть некоторое недопонимание, но я думаю, что мы можем его прояснить.
Первый [аргумент
cons
] может быть символом или списком, это не имеет значения. Но особенно второй элемент должен быть символом, если это не так, может быть, например, списком, то мы не можем создать пару со встроенной процедурой cons.
Это не правильно. Ты можешь позвонить cons
с любыми аргументами, которые вам нравятся, и вы всегда получите ответ cons
клетка, чья car
такой же, как первый аргумент cons
и чей cdr
такой же, как второй аргумент cons
, То есть единственное, что важно о cons
является то, что он удовлетворяет уравнениям
(eq? a (car (cons a b))
(eq? b (cdr (cons a b))
Так можно ли создать пару из 2 списков??? Ну, я думаю, что решение состоит в том, что преобразование списка в символ, но на самом деле это две совершенно разные вещи -> невозможно, как я понимаю.
Это вполне возможно; если у вас есть два списка, например, list1
а также list2
, вы можете создать пару, чья car
является list1
и чей cdr
является list2
просто позвонив (cons list1 list2)
, Теперь я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, что вы ожидаете увидеть (<value-of-list1> . <value-of-list2>)
в качестве выхода, и вы видите что-то другое. Чтобы объяснить, почему это так, нам нужно понять, как списки представлены в Лиспе и как распечатываются пары.
Список в Схеме - это либо пустой список ()
(также известен как nil
в некоторых Лиспах), или против car
(также известен как first
) является элементом списка и чей cdr
(также известен как rest
) либо остальная часть списка (т. е. другой список), либо атом, который завершает список. Условный терминатор - пустой список ()
; списки завершены ()
называются "правильные списки". Списки, оканчивающиеся любым другим атомом, называются "неподходящими списками". Список (1 2 3 4 5)
содержит элементы 1, 2, 3, 4 и 5 и заканчивается ()
, Вы могли бы построить это путем
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))
Теперь, когда система печатает ячейку "против", общий случай состоит в том, чтобы напечатать ее
(car . cdr)
Например, результат (cons 1 2)
печатается как
(1 . 2)
Поскольку списки построены из cons-ячеек, вы также можете использовать эту запись для списков:
'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))
Однако это довольно неуклюже, поэтому у большинства списков (все, что я знаю) есть особый случай для печати против клеток: если cdr
это список (либо другая ячейка минусов, либо ()
), то не печатайте .
и не печатать окружающие скобки cdr
(что было бы иначе, так как это список).
Теперь мы можем объяснить, почему результат (cons list1 list2)
не похоже (<value-of-list1> . <value-of-list2>)
, Если вы позвоните cons
с двумя списками, вы получите пару с ожидаемым car
а также cdr
, но это не напечатано с .
нотации. Например,
(cons '(1 2 3) '(a b c))
;=> ((1 2 3) . (a b c)) ; which is typically *printed* as
;=> ((1 2 3) a b c)
Но опять же, печатное представление на самом деле не имеет значения, пока выполняются следующие уравнения:
(eq? a (car (cons a b))
(eq? b (cdr (cons a b))
Конечно же:
(car (cons '(1 2 3) '(a b c)))
;=> (1 2 3)
(cdr (cons '(1 2 3) '(a b c)))
;=> (a b c)
В конкретном примере, о котором вы спрашиваете, подумайте, что происходит, когда вы звоните
(cons '(prov:label "entity e0") '(prov:location "London"))
Результат, на самом деле,
((prov:label "entity e0") . (prov:location "London"))
но из-за правил печати это печатается как
((prov:label "entity e0") prov:location "London")
Тем не менее, вы можете получить два атрибута, используя car
а также cdr
:
(car '((prov:label "entity e0") prov:location "London"))
;=> (prov:label "entity e0")
(cdr '((prov:label "entity e0") prov:location "London"))
;=> (prov:location "London")
и это все, что вам нужно сделать позже.
Точечная запись в Схеме или любом другом диалекте LISP по этому вопросу используется для создания точечной пары любых двух значений. Значения могут быть символами, списками или чем-то еще. Это действительно не имеет значения, что это такое. Например:
'(author . aaditmshah) => (author . aaditmshah)
'((a b c) . (d e f)) => ((a b c) d e f)
Как вы можете видеть, если вы создадите пунктирную пару из двух списков, тогда первый список будет добавлен в заголовок второго списка. Это связано с тем, что списки в LISP являются вложенными точечными парами:
'(a . (b . (c . ()))) => '(a b c)
Следовательно, когда вы пишете '((a b c) . (d e f))
это как если бы вы писали следующее:
'((a b c) . (d . (e . (f . ())))) => '((a b c) d e f)
Это совершенно верно. Вы по-прежнему можете получить доступ к обоим спискам по отдельности, используя car
а также cdr
как обычно:
(car '((a b c) . (d e f))) => (a b c)
(cdr '((a b c) . (d e f))) => (d e f)
Я не уверен, что ты compare-attrs
функция должна делать. Ваш if
филиал возвращает cons
клетка в то время как ваш else
ответвление возвращает логическое значение. Для меня это абсолютно бессмысленно. Тип возвращаемого значения функции должен быть постоянным.
Возможно, вы не правильно сформулировали свой вопрос, потому что я не совсем уверен, в чем ваша проблема. Дайте мне знать, если у вас все еще есть сомнения.
Мое воспоминание о структурировании данных в схеме состоит в том, что вы бы предпочли избегать пунктирной пары атомов (т.е. (a . b)
), поскольку это представляет собой результат объединения двух атомов вместе. Если вы заглянете в "Маленький интриган", стр. 3, вы увидите следующее:
Закон минусов
Примитивные минусы принимает два аргумента. Вторым аргументом в пользу cons должен быть список. Результатом является список.
если вы читали другие ответы, вы знаете, что это не так. Так что, честно говоря, главное, что нужно сделать с структурированием данных Scheme, которое запрещено SICP, - определить структуру структуры данных в виде списков, а затем создать небольшие функции, которые будут действовать как средства доступа.
Итак, скажем, что вы хотите иметь кортеж - вы можете сделать его похожим (a b)
что вполне разумно Тогда вы можете написать эти функции:
(define (make-tuple a b) (list a b))
(define (tuple-first tup) (car tup))
(define (tuple-second tup) (car (cdr tup)))
(define (tuple? tup) (and (list? tup) (eq? 2 (length tup))))
который теперь дает мне функции доступа и конструктор, и я золото. Но это не значит, что это единственный способ сделать это. Вы можете пойти дальше и использовать пары тоже:
(define (make-tuple a b) (cons a b))
(define (tuple-first tup) (car tup))
(define (tuple-second tup) (cdr tup))
(define (tuple? tup) (pair? tup))
Таким образом, в вашем коде вы можете использовать конструктор здесь, чтобы создать нужный вам кортеж.
В общем, ваша функция сравнения-приписывания странная в том смысле, что имя на самом деле не дает нам представления о том, что вы пытаетесь сделать. Я был бы более склонен написать это так:
(define (compare-attrs a1 a2)
(or
(and (null? a1) (null? a2))
(and (not (null? a1)) (not (null? a2)))
))
(define (join-populated-attrs a1 a2)
(if (compare-attrs a1 a2) (make-tuple a1 a2) '()))
что все еще кажется забавным в том, что вы принимаете два нулевых атрибута, но это, вероятно, часть вашей проблемной области.
Я также должен сказать, что если вы хотите, чтобы вывод отображался определенным образом, вам, вероятно, следует написать print-tuple
также.