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
384 views
in Technique[技术] by (71.8m points)

scheme - Recursive range in Lisp adds a period?

(define ..
  (lambda (start stop)
    (cond ((> (add1 start) stop) (quote ()))
          ((eq? (add1 start) stop) (sub1 stop))
          (else (cons start (.. (add1 start) stop))))))

I have defined a simple range function. The intent is for

(.. 1 5)  -->  (1 2 3 4)

Instead, a bizarre period is being added to my tuple and I have no idea why:

(.. 1 5)  -->  (1 2 3 . 4)

I don't understand why this is happening. Any help is appreciated

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

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). So, if you're seeing a result like

(1 2 3 . 4)

it means you've got an improper list that is terminated by the atom 4. It has the structure

(1 . (2 . (3 . 4)))

Now the question is: where in your code did the list construction go awry? .. is always supposed to return a proper list, so let's look at the cases: The first case always returns a proper list (the empty list):

((> (add1 start) stop) (quote ()))

The second case looks like it can return something that's not a list (assuming that (sub1 stop) == (- stop 1)):

((eq? (add1 start) stop) (sub1 stop))

Now, if .. were functioning correctly, then the third case would always be returning a proper list (since (cons x y) is a proper list if y is):

(else (cons start (.. (add1 start) stop)))

Make your second case return a list and you should be all set.


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

1.4m articles

1.4m replys

5 comments

57.0k users

...