Scheme 仅使用“中的表格”展平列表;“小阴谋家”;

Scheme 仅使用“中的表格”展平列表;“小阴谋家”;,scheme,the-little-schemer,Scheme,The Little Schemer,我正在学习小Schemer来学习Scheme(作为一个老的C程序员),作为练习,我试图编写一个过程,仅使用小Schemer中的表单来压平列表;即,定义,lambda,条件,汽车,cdr,和,或等,但不包括附加。我认为这很容易,但我还没有想出一个解决办法。我怎样才能做到这一点呢?我不熟悉小Schemer原语,因此您可能需要对其进行调整以适应 我不确定这是否是您想要的答案,但您可以使用原语编写append: (define (append l1 l2) (cond ((null? l1)

我正在学习小Schemer来学习Scheme(作为一个老的C程序员),作为练习,我试图编写一个过程,仅使用小Schemer中的表单来压平列表;即,
定义
lambda
条件
汽车
cdr
等,但不包括
附加
。我认为这很容易,但我还没有想出一个解决办法。我怎样才能做到这一点呢?

我不熟悉小Schemer原语,因此您可能需要对其进行调整以适应

我不确定这是否是您想要的答案,但您可以使用原语编写
append

(define (append l1 l2)
  (cond
    ((null? l1) l2)
    (else (cons (car l1) (append (cdr l1) l2)))))
然后就可以用这个函数编写
flatte
函数


不确定这是否超出规则:)

这是一个尝试。它不需要使用cons和避免append,因为它只需要切掉它可以到达的第一个非对,并使用它已经构建的新尾巴的扁平化。有时它会重写列表,然后再次调用Flatte。Def不是最有效的方法

固定代码:

(define (flatten x)
  (cond 
    ((null? x) x)
    ((and (pair? x) 
          (not (pair? (car x))))
     (cond 
       ((null? (car x)) (flatten (cdr x)))
       (else (cons (car x) (flatten (cdr x))))))
    ((and (pair? x)
          (pair? (car x)))
     (flatten (cons (caar x) 
                    (cons (cdar x) (cdr x)))))
    (else (cons x '()))))

我有一个版本,它只使用“第一原则”操作,而且效率很高(与基于
append
的解决方案不同,它不需要多次遍历任何列表)。:-)

它通过定义两个简单的构建块(
fold
reverse
),然后在这些构建块上定义
flatten
(及其助手,
reverse flatte into
)(注意每个函数只有一行或两行长):

使用的唯一外部功能是:
cons
car
cdr
null?
pair?


这个函数的关键之处在于
fold
是一个非常强大的操作,应该是任何Schemer工具箱的一部分。而且,正如上面的代码所示,从第一原则构建非常简单

谢谢,这正是我想要的。谢谢!最好使用
list?
而不是
pair?
来处理要展平的输入列表为空的情况(感谢chrislck on#guile为我指出了这个示例和这个小错误)
;; Similar to SRFI 1's fold
(define (fold1 kons knil lst)
  (if (null? lst)
      knil
      (fold1 kons (kons (car lst) knil) (cdr lst))))

;; Same as R5RS's reverse
(define (reverse lst)
  (fold1 cons '() lst))

;; Helper function
(define (reverse-flatten-into x lst)
  (if (pair? x)
      (fold1 reverse-flatten-into lst x)
      (cons x lst)))

(define (flatten . lst)
  (reverse (reverse-flatten-into lst '())))