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。如果他们叫我异教徒,我就是异教徒^_^