如何编写一个 Scheme 过程,它采用格式错误的列表和 returns 具有相同结构的格式正确的列表?

How to write a Scheme procedure which takes an ill formed list and returns a well formed one with the same structure?

我正在尝试实现一个 Scheme 过程,它采用可能格式不正确的嵌套数字列表和 returns 具有相同内容和结构但没有任何点的嵌套列表显示时。

示例:

scm> (reform '((1 . 2) 3))
((1 2) 3)
scm> (reform '(1 (2 3 . 4) . 3))
(1 (2 3 4) 3)
scm> (reform '(1 . ((2 3 . 4) . 3)))
(1 (2 3 4) 3)

我目前的解决方案:

(define (reform s)
  (cond
   ((null? s) nil)
   ((number? s) s)
   ((null? (cdr s)) (car s))
   (else (list (reform (car s)) (reform (cdr s))))
  )
)

这个解决方案确实删除了所有的点,但它不保持输入的形式。我如何重写我的实现,以便它不会创建输入中不存在的额外列表?

这通过了测试。

(define (reform xs)
  (cond
    [(null? xs) xs]
    [(and (pair? xs) (pair? (cdr xs)))
     (cons (reform (car xs)) (reform (cdr xs)))]
    [(and (pair? xs) (null? (cdr xs)))
     (list (reform (car xs)))]
    [(pair? xs)
     (cons (reform (car xs)) (list (reform (cdr xs))))]
    [else xs]))

(reform '((1 . 2) 3))
(reform '(1 (2 3 . 4) . 3))
(reform '(1 . ((2 3 . 4) . 3)))

不确定为什么@soegaard 有这么多测试,如果列表是一对,而显而易见的是首先执行异常:

(define (dot->proper xs)
  (cond ((null? xs) '())
        ((not (pair? xs)) (list xs))
        ((pair? (car xs)) (cons (dot->proper (car xs)) (dot->proper (cdr xs))))
        (else  (cons (car xs) (dot->proper (cdr xs))))))

(dot->proper '((1 . 2) 3))           ; ==> ((1 2) 3)
(dot->proper '(1 (2 3 . 4) . 3))     ; ==> (1 (2 3 4) 3)
(dot->proper '(1 . ((2 3 . 4) . 3))) ; ==> (1 (2 3 4) 3)