计划中的点符号
我是Scheme编程的初学者。 我知道Scheme中的点符号用来表示一对符号,例如'(a . b)
。
第一个元素可能是一个符号,或者一个列表,没关系。 但特别是第二个元素必须是一个符号,如果不是,可能是一个列表,那么我们不能创build一个内置的cons
过程的对。
那么是否有可能创build一个2列表对? 那么我想一个解决scheme是将列表转换为符号,但实际上这是完全不同的事情 – >我不明白。
这是我写的代码:
(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)
请解释一下。 预先感谢!!!
编辑:添加使用比较attrsfunction
函数compare-att用于提取描述实体属性的部分,并使它们成对,定义如下的实体:
(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")`
注意:这是从Lisp的一个答案递解范围中添加一个句点? ,这实际上是在问一个不同的问题。 但是,如何打印对的解释是相同的。 其余的答案是不同的。
你的问题performance出一些误解,但我认为我们可以清除它。
第一个[反对论]可能是一个符号,或一个列表,这并不重要。 但特别是第二个元素必须是一个符号,如果不是,可能是一个列表,那么我们不能创build一个内置的cons过程的对。
这是不正确的。 你可以用你喜欢的任何论点来打电话给你,你总是会找回一个与cons
第一个参数相同的cons
cell,而它的cdr
与cons
的第二个参数相同。 也就是说,唯一重要的是它满足方程
(eq? a (car (cons ab)) (eq? b (cdr (cons ab))
那么是否有可能创build一个2列表对? 那么我想一个解决scheme是将列表转换为符号,但实际上这是完全不同的事情 – >我不明白。
这很可能; 如果你有两个列表,例如list1
和list2
,你可以通过调用(cons list1 list2)
来创build一个car
为list1
和cdr
为list2
。 现在,我认为你遇到的问题是,你期待看到 (<value-of-list1> . <value-of-list2>)
作为输出,你看到一些不同的。 为了解释这是为什么,我们需要了解如何在Lisp中表示列表,以及如何打印对。
Scheme中的列表可以是空列表()
(也称为某些Lisp中的nil
),也可以是其car
(也称为first
)是列表元素并且其cdr
(也称为rest
)的cons单元列表的其余部分(即另一个列表)或终止列表的primefaces。 传统的终结者是空列表()
; 被()
终止的列表被认为是“正确的列表”。 任何其他primefaces终止的列表被称为“不正确的列表”。 列表(1 2 3 4 5)
包含元素1,2,3,4和5,并以()
结束。 你可以通过构build它
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))
现在,当系统打印一个黑格,一般的情况是打印一下
(car . cdr)
例如, (cons 1 2)
的结果被打印为
(1 . 2)
由于列表是由cons单元格构build的,因此您也可以使用这种表示法:
'(1 2 3 4 5) == '(1 . (2 . (3 . (4 . (5 . ())))))
尽pipe如此,所以大多数人(我所知道的)都有一个特殊的情况来打印cons单元格:如果cdr
是一个列表(或者是另一个单元格,或者是),那么不要打印该列表.
,不要打印cdr
的周围圆括号(否则它会有,因为它是一个列表)。
现在我们可以解释为什么(cons list1 list2)
的结果看起来不像(<value-of-list1> . <value-of-list2>)
。 如果你打电话给两个名单,你会得到一个与预期的car
和car
,但它没有与打印.
符号。 例如,
(cons '(1 2 3) '(abc)) ;=> ((1 2 3) . (abc)) ; which is typically *printed* as ;=> ((1 2 3) abc)
但是,再次,打印的表示并不重要,只要以下公式成立:
(eq? a (car (cons ab)) (eq? b (cdr (cons ab))
果然:
(car (cons '(1 2 3) '(abc))) ;=> (1 2 3) (cdr (cons '(1 2 3) '(abc))) ;=> (abc)
在你问的具体例子中,考虑当你打电话时会发生什么
(cons '(prov:label "entity e0") '(prov:location "London"))
结果是,事实上,
((prov:label "entity e0") . (prov:location "London"))
但是,由于打印规则,这被打印为
((prov:label "entity e0") prov:location "London")
尽pipe如此,你仍然可以通过使用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")
这就是你以后需要做的一切。
Scheme中的点符号或任何其他LISP方言用于创build任何两个值的点对。 值可以是符号,列表或其他任何东西。 它是什么价值真的没有关系。 例如:
'(author . aaditmshah) => (author . aaditmshah) '((abc) . (def)) => ((abc) def)
正如你可以看到,如果你创build一个两个列表的虚线对,那么第一个列表将被添加到第二个列表的头部。 这是因为LISP中的列表是嵌套点对:
'(a . (b . (c . ()))) => '(abc)
因此,当你写'((abc) . (def))
,就好像你正在写下面的内容:
'((abc) . (d . (e . (f . ())))) => '((abc) def)
这是完全有效的。 您仍然可以像往常一样使用car
和cdr
单独访问这两个列表:
(car '((abc) . (def))) => (abc) (cdr '((abc) . (def))) => (def)
我不确定你的compare-attrs
函数应该做什么。 你的if
分支返回一个cons
单元,而你的else
分支返回一个布尔值。 对我来说这绝对没有意义。 函数的返回types应该是常量。
也许你没有正确expression你的问题,因为我不确定你的问题是什么。 让我知道你是否还有疑问。
我关于数据结构化scheme的回忆是,你宁愿避免一对primefaces(即(a . b)
a。b (a . b)
),因为它代表了两个primefaces结合在一起的结果。 如果你看第3页的The Little Schemer ,你会看到:
缺点法则
原始缺点有两个论点。 利弊第二个参数必须是一个列表。 结果是一个列表。
如果你读过其他的答案,你知道这是不正确的。 诚实地说, SICP所禁止的Scheme数据结构的事情是用列表的方式来定义你的数据结构布局,然后再做一些小function来作为访问者。
所以,假设你想要一个元组 – 你可以使它看起来像(ab)
这是完全合理的。 那么你可以写这些function:
(define (make-tuple ab) (list ab)) (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 ab) (cons ab)) (define (tuple-first tup) (car tup)) (define (tuple-second tup) (cdr tup)) (define (tuple? tup) (pair? tup))
所以在你的代码中,你可以使用这里的构造函数来创build你想要的元组。
一般来说,你的compare-attrs函数很奇怪,因为这个名字并不能真正让我们知道你在做什么。 我更倾向于这样写:
(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) '()))
这仍然感到有趣,因为你接受两个null属性,但这可能是你所有问题域的一部分。
我也应该说,如果你希望输出以一种特定的方式出现,你也应该写print-tuple
。