如何在 Lisp R5RS 中编写幂集

How to code Power Set in Lisp R5RS

我是函数式编程的新手,我不知道如何用 Lisp 编写代码。例如,对于给定的幂集,例如 (1 2 3),我如何以某种方式对其进行编码:(不使用 Lambda 函数) ( () (1) (2) (3) (1 2 3) )

到目前为止,我有:

(define  (powerSet lis)
  (if (null? lis) '(()))
 )

(define (APPENDS lis1 lis2)
   (cond
   ((null? lis1) lis2)
        (else (cons (car lis1)
            (APPENDS (cdr lis1) lis2)))
  )
)

这只是 returns 空集,或者什么都没有。

编辑:

非常感谢克里斯!这很有道理。第二种变体(没有 append-map 函数)效果很好。但是,如果您输入 (powerset'(1 2 3 4)),它会为您提供:

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

我有没有办法让它看起来像:

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

非常感谢!

所有 用户定义函数都是 lambda(或 case-lambda)表达式,包括您正在定义的 powerset 函数。没有办法避免它。但是,您可以使用内部定义 隐藏 lambda 标识符(它仍然是幕后的 lambda!)。

考虑到这一点,这里有一个实现(需要 Racket 或 SRFI 1):

(define (powerset lst)
  (define (make-pair x)
    (list x (cons (car lst) x)))
  (if (null? lst)
      '(())
      (append-map make-pair (powerset (cdr lst)))))

如果你想避免 append-map 或一般的高阶函数,你可以跳过几个步骤来做同样的事情:

(define (powerset lst)
  (define (inner next)
    (if (null? next)
        '()
        (cons (car next)
              (cons (cons (car lst) (car next))
                    (inner (cdr next))))))
  (if (null? lst)
      '(())
      (inner (powerset (cdr lst)))))

这样的表达式
(define (foo bar)
  baz)

实际上展开为如下等价表达式:

(define foo
  (lambda (bar)
    baz))