Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
121 views
in Technique[技术] by (71.8m points)

Dot notation in scheme

I'm a beginner in Scheme programming. I know that the dot notation in Scheme is used to present a pair of symbol, for example '(a . b).

The first element could be a symbol, or a list, it doesn't matter. But specially the second element must be a symbol, if it is not, may be a list for instance, then we can't create a pair with built-in cons procedure.

So is it possible to create a pair of 2 lists??? Well i'm thinking of a solution is that converting a list to symbol but actually those are 2 completely different thing -> impossible as i understand.

This is the code i wrote:

(define compare-attrs
  (lambda (attribute1 attribute2)
    (if (or (and (null? attribute1) (null? attribute2)) (and (not (null? attribute1)) (not (null? attribute2))))
        (cons attribute1 attribute2)
        #f)))

In which attribute1 and attribute2 is 2 lists, and my output is:

attribute1 atrribute2

Expected output: '(attribute1 . attribute2)

Please explain this. Thank in advance!!!

EDIT: adding the use of compare-attrs function

The function compare-attrs used to extract the part that describes attributes of entities and cons them to make a pair, entities defined defined below:

(entity e0 (prov:label "entity e0")
(entity e1 (prov:location "London")

so attribute of these entities are (prov:label "entity e0") and (prov:location "London"). When apply the function compare-attrs, because these attributes are not null, so that the output i expect is

`(prov:label "entity e0") . (prov:location "London")`
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Note: this is cannibalized from an answer to Recursive range in Lisp adds a period?, which is really asking a different question. However, the explanation of how pairs are printed is the same. The rest of the answer is different.

Your question exhibits a bit of misunderstanding, but I think we can clear it up.

The first [argument to cons] could be a symbol, or a list, it doesn't matter. But specially the second element must be a symbol, if it is not, may be a list for instance, then we can't create a pair with built-in cons procedure.

This is not correct. You can call cons with whatever arguments you like, and you will always get back a cons cell whose car is the same as the first argument to cons, and whose cdr is the same as the second argument to cons. That is, the only thing that's important about cons is that it satisfies the equations

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

So is it possible to create a pair of 2 lists??? Well i'm thinking of a solution is that converting a list to symbol but actually those are 2 completely different thing -> impossible as i understand.

It's quite possible; if you have two lists, e.g., list1 and list2, you can create a pair whose car is list1 and whose cdr is list2 just by calling (cons list1 list2). Now, I think the issue that you're running up against is that you're expecting to see (<value-of-list1> . <value-of-list2>) as the output, and you're seeing some different. To explain why this is, we need to understand how lists are represented in Lisps, and how pairs are printed.

A list in Scheme is either the empty list () (also known as nil in some Lisps), or a cons cell whose car (also known as first) is an element of the list and whose cdr (also known as rest) is either the rest of the list (i.e., another list), or an atom that terminates the list. The conventional terminator is the empty list (); lists terminated by () are said to be "proper lists". Lists terminated by any other atom are called "improper lists". The list (1 2 3 4 5) contains the elements 1, 2, 3, 4, and 5, and is terminated by (). You could construct it by

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))

Now, when the system prints a cons cell, the general case is to print it by

(car . cdr)

For instance, the result of (cons 1 2) is printed as

(1 . 2)

Since lists are built of cons cells, you can use this notation for lists too:

'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))

That's rather clunky, though, so most lisps (all that I know of) have a special case for printing cons cells: if the cdr is a list (either another cons cell, or ()), then don't print the ., and don't print the surrounding parenthesis of the cdr (which it would otherwise have, since it's a list).

Now we can explain why the result of (cons list1 list2) doesn't look like (<value-of-list1> . <value-of-list2>). If you call cons with two lists, you do get back a pair with the expected car and cdr, but it's not printed with the . notation. E.g.,

(cons '(1 2 3) '(a b c))
;=> ((1 2 3) . (a b c))   ; which is typically *printed* as
;=> ((1 2 3) a b c)

But again, the printed representation doesn't really matter though, as long as the following equations hold:

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

Sure enough:

(car (cons '(1 2 3) '(a b c)))
;=> (1 2 3)

(cdr (cons '(1 2 3) '(a b c)))
;=> (a b c)

In the specific example you're asking about, consider what happens when you call

(cons '(prov:label "entity e0") '(prov:location "London"))

The result is, in fact,

((prov:label "entity e0") . (prov:location "London"))

but, because of the printing rules, this is printed as

((prov:label "entity e0") prov:location "London")

Nonetheless, you can still get the two attributes out by using car and cdr:

(car '((prov:label "entity e0") prov:location "London"))
;=> (prov:label "entity e0")

(cdr '((prov:label "entity e0") prov:location "London"))
;=> (prov:location "London")

and that's all you really need to be able to do later.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...