计划中的点符号

我是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,而它的cdrcons的第二个参数相同。 也就是说,唯一重要的是它满足方程

 (eq? a (car (cons ab)) (eq? b (cdr (cons ab)) 

那么是否有可能创build一个2列表对? 那么我想一个解决scheme是将列表转换为符号,但实际上这是完全不同的事情 – >我不明白。

这很可能; 如果你有两个列表,例如list1list2 ,你可以通过调用(cons list1 list2)来创build一个carlist1cdrlist2 。 现在,我认为你遇到的问题是,你期待看到 (<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>) 。 如果你打电话给两个名单,你得到一个与预期的carcar ,但它没有与打印. 符号。 例如,

 (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如此,你仍然可以通过使用carcdr来获得这两个属性:

 (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) 

这是完全有效的。 您仍然可以像往常一样使用carcdr单独访问这两个列表:

 (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