Home > OS >  Scheme output has extra parenthesis and periods
Scheme output has extra parenthesis and periods

Time:08-11

I started learning Scheme today, and wanted to write a function that would reverse a list (only surface level, nested lists stay in the same order).

Heres the function I made:

(define reverse (lambda (lst)
                  (if (> (length lst) 0)
                      (cons (reverse(cdr lst)) (car lst))
                      '()
                      )))

I thought it would just continuously add the values before everything after it so in the end it's reversed, but when doing (reverse '(5 12 31 7 98 13)), I should get (13 98 7 31 12 5), but instead I get '((((((() . 13) . 98) . 7) . 31) . 12) . 5). How come it's adding periods and parenthesis instead of adding the number to the list?

CodePudding user response:

(list x y ..... z) list structure is constructed like this in Scheme:

(cons x
      (cons y
            …
            …
            (cons z '())))

if you use append instead of cons and put your (car lst) into a list of its own, your code will work:

(define reverse 
   (lambda (lst)
     (if (> (length lst) 0)
         ;;(cons (reverse (cdr lst))       (car lst) )
         (append (reverse (cdr lst)) (list (car lst)))
         '()
     )))

CodePudding user response:

The list (13 98 7 31 12 5) is a visualization of the pairs (13 . (98 . (7 . (31 . (12 . (5 . ())))))). If the cdr is a pair or the empty list the dot and one set of parens is omitted. The code to create this structure is (cons 13 (cons 98 (cons 7 (cons 31 (cons 12 (cons 5 '())))))) while the structure your function creates is (cons (cons (cons (cons (cons (cons 13 '()) 98) 7) 31) 12) 5).

When iterating a list you always do it in order. eg. (1 2 3) is quite difficult to do in reverse. However when creating lists you always do them from end to beginning. eg. (cons 1 (cons 2 (cons 3 '()))) will have to evaluate the cons with 3 before the one with 2 etc. This can be used for a very efficent reverse using an accumulator:

(define (reverse lst acc)
  (if (null? lst)
      acc
      (reverse (cdr lst) 
               (cons (car lst) acc))))

So imagine calling this (reverse '(1 2 3) '()):

(reverse '(1 2 3) '())        ; => 
(reverse '(2 3) (cons 1 '())) ; ==> 
(reverse '(3) (cons 2 '(1)))  ; ==> 
(reverse '() (cons 3 '(2 1))) ; ==> 
'(3 2 1)
  • Related