Common lisp LISP中的函数式编程

Common lisp LISP中的函数式编程,common-lisp,clisp,Common Lisp,Clisp,我刚刚开始学习函数编程,这让我有点困惑,我现在有一个任务:删除列表行中的所有重复项,因此: 输入行: (SETQ X (LIST 2 -3 (LIST 4 3 0 2) (LIST 4 -4) (LIST 2 (LIST 2 0 2))-3)) 我希望输出是这样的:(2-3(430)(-4)() 我想用递归实现它。 我有一些概念性的问题:如何从列表中删除一个元素,或者应该为输出创建一个新的元素?在其他编程语言中,递归的每一步都有自己的变量作用域,这里是否相同?请你描述一下,你会怎么做 顺便

我刚刚开始学习函数编程,这让我有点困惑,我现在有一个任务:删除列表行中的所有重复项,因此: 输入行:

(SETQ X (LIST  2 -3 (LIST 4 3 0 2) (LIST 4 -4) (LIST 2 (LIST 2 0 2))-3)) 
我希望输出是这样的:(2-3(430)(-4)() 我想用递归实现它。 我有一些概念性的问题:如何从列表中删除一个元素,或者应该为输出创建一个新的元素?在其他编程语言中,递归的每一步都有自己的变量作用域,这里是否相同?请你描述一下,你会怎么做

顺便说一句,我正在尝试运行以下代码:

(SETQ X (LIST  2 -3 (LIST 4 3 0 2) (LIST 4 -4) (LIST 2 (LIST 2 0 2))-3))(DEFUN SEARCHDEEP (WHAT WHERE)
(COND
    ((NULL WHERE) NIL)
    (T (OR 
            (COND 
                ((ATOM (CAR WHERE)) (EQUAL WHAT (CAR WHERE)))
                (T (SEARCHDEEP WHAT  (CAR WHERE)))
            )
            (SEARCHDEEP WHAT (CDR WHERE))
        )
    )
))

(DEFUN REMDOUBLES (INPUT OUTPUT)(
(COND 
    ((NULL INPUT) NILL)
    (T 
        (REMDOUBLES (CDR INPUT) OUTPUT)
        (PRINT INPUT)
    )
)))


(REMDOUBLES X NIL)
但是我得到了这个错误,它意味着什么


SYSTEM::%EXPAND-FORM:(COND((NULL输入)NILL)(T(REMDOUBLES(CDR输入)输出)(PRINT输入)))应该是lambda表达式

我不知道公共Lisp,但我为您提供了一个使用racket的解决方案。将其转换为Lisp应该很简单,但我将把它作为一项任务留给您。因为这可能是一个家庭作业,所以通过代码并理解它对你来说是件好事

我认为我使用的唯一特定于racket的东西是racket的,它只是用来在我们将唯一值添加到输出时跟踪它们。该集合在过程的计算完成后被丢弃

#lang racket

(define input (list  2 -3 (list 4 3 0 2) (list 4 -4) (list 2 (list 2 0 2)) -3))

(define (procedure xs)
  (define (aux acc s xs)
    (cond [(empty? xs) (reverse acc)]
          [(list? (car xs)) (aux (cons (aux empty s (car xs)) acc) s (cdr xs))]
          [(set-member? s (car xs)) (aux acc s (cdr xs))]
          [else (begin (set-add! s (car xs))
                       (aux (cons (car xs) acc) s (cdr xs)))]))
  (aux empty (mutable-set) xs))

(define output (my-procedure input))

(display output)
; => (2 -3 (4 3 0) (-4) (()))

这有点复杂,因为它将树递归、折叠和唯一过滤混合在一个过程中。更好的解决方案是将这些过程分离为通用过程,然后将它们组合在一个更具声明性的最终过程中,以完成您的预期任务。

在函数式编程中,您不会从参数中删除元素,因此您最有可能创建一个新列表,但在许多情况下,您可以共享结构(尾部)在论点和结果中是相同的

公共Lisp是词汇范围的。这意味着,在创建函数时存在的自由变量加上全局作用域,除了绑定变量之外是已知的,绑定变量在每次使用时都会被绑定,就像您可能知道的其他语言一样

“something should a lambda expression”是一个常见的Lisp错误,当您尝试将表达式置于运算符位置时。例如,方案代码
((如果(
根据操作数位置表达式的计算结果变为
15
-5
。在Common lisp中,您可以有一个符号,例如
(+12)
中的
+
,或者一个lambda,例如
((lambda(x)(*x))10)
。您尝试了
((cond…)
,它可以在Scheme中工作,但不能在Common Lisp中工作。在CommonLisp中,您需要执行
(funcall(if(
。由于括号在C中几乎都是卷曲的,我猜它们放错了位置,就像有人在
someFun(arg)(
语句的末尾添加了一组()一样,而
someFun
没有返回函数

我会像这样解决您的代码:

;; setq is for mutating, defparameter is a good option to make a global variable 
(defparameter *test* '(2 -3 (4 3 0 2) (4 -4) (2 (2 0 2)) -3))

(defun unique-elements (lst)
  (let ((h (make-hash-table :test 'equal)))
    (labels ((aux (lst)
               (cond ((null lst) '())
                     ((consp (car lst))
                      (let ((a (aux (car lst))))
                        (if (null a)
                            (aux (cdr lst)) ; don't include empty elements
                            (cons a (aux (cdr lst))))))
                     ((gethash (car lst) h)
                      (aux (cdr lst)))
                     (t (setf (gethash (car lst) h) t)
                        (cons (car lst) (aux (cdr lst)))))))
      (aux lst))))

(unique-elements *test*) ; ==> (2 -3 (4 3 0) (-4))

你说的lisp是什么意思,
common lisp
emacs lisp
还有别的什么吗?据我所知,它叫execute lisp,我使用这个网站作为编译器@user1034749,我试图运行问题中的代码(刚刚添加的代码),只是想看看递归将如何倒退,你能帮我一下吗?你把函数体用括号括起来了。这就像在C#中放入额外的(),例如
returnsomefun()。CL是一个lisp 2,因此您需要执行
(funcall(cond…)
,并且cond需要返回一个函数。没有一种称为Execute lisp的语言。该网站只是说“你可以在我们的web应用程序上执行LISP命令”。我用
lisp实现类型为您检查了一下,该网站正在运行CLISP,这是一个常见lisp的ANSI实现。回答得很好。关于Common Lisp,我学到了一两件事^ ^如果你否决了我的答案(我怀疑你是否否决了),你能至少让我知道我的答案可以改进吗?@naomik,我没有。lisp社区在1对2的名称空间中是宗教性的,所以即使我在回答中提到这个方案,也可能会让我投反对票,所以我猜用“错误的语言”回答可能会被认为是亵渎。啊,好的,谢谢@Sylvester。如果他们叫我异教徒,我就是异教徒^_^