LISP常用列表功能

时间:2016-05-14 19:27:26

标签: lisp

嘿伙计们我有最后一个问题我试图为我的学期解决问题。我需要创建:

(myCommon L1 L2)
Evaluates to a list of elements that are common in both lists L1 and L2.
Assume L1 and L2 have no repeated elements.
eg.  (myCommon ‘(p a e g) ‘(a q r e))  →  (a e)

我只能使用以下功能:

(atom X)            
(quote X)           
‘X          
(eq X Y)            
(cons X L)          
(car L)         
(cdr L)         
(list A B C)        
(if X Y Z)      .
(cond (C1 S1) (C2 S2) …… (Cn Sn))       
(lambda (P1 P2 …… Pn) E)        
(funcall F (P1 P2 …… Pn))   

我也可以使用我在作业中创建的功能。到目前为止,我创建了:

(defun myLast (L) 
  (if (eq (cdr L) '()) 
  (car L) 
  (myLast (cdr L))))               ;Evaluates to the last element of list L

(defun myCount (X L)
   (cond ((eq L '()) 0)
     ((eq X (car L))(+ 1 (myCount X (cdr L))))
     (+ (myCount X (cdr L)))))   ;Evaluates to number of occurrences of X in L

(defun myMember (X L)
   (cond ((eq L '()) '())
   ((eq X (car L)) t)
   (t (myMember X (cdr L)))))   ;Evaluates to true if X in L, false otherwise

这项任务的问题是我不能与老师见面,因为他已经离开,并且现在“有限的电子邮件访问”。我无法提出如何解决这个问题的问题,即使在这个功能的起点,我也很困惑。我想我必须像L1的汽车一样使用myMember并检查它是否在L2中,如果它被放入一个新列表并递归添加到列表中。我不知道该怎么做。任何人都可以帮助我,所以我终于可以完成这个学期了吗?谢谢!

1 个答案:

答案 0 :(得分:2)

你的想法很好。你应该看看你在myCount中使用的模式。你可以为myCommon使用几乎相同的模式。

考虑如何摆脱递归。您正在构建一个列表,而不是一个数字,因此不要将0作为终值,而应考虑列表的结尾。

对于递归子句,当您应该包含该项时,不要使用+ 1,而是使用将项添加到列表的函数。

请记住只递归myCommon中的一个列表。您应该一次查看一个元素,并将该元素与完整的第二个列表进行比较,为了myCommon的目的,该列表应该是一个常量。

希望这能够帮助您实现您以前职能的精神。但这是实现交叉函数的一种非常低效的方法。

一个可以帮助编译器生成更高效代码的常用技巧是使用带有第三个参数的辅助函数 - 当你递归一个输入列表时构建的累加器。 (累加器技巧允许您以称为尾部重复的样式编写函数。)

当你没有做人工限制的练习以学习递归时,我宁愿使用迭代(loopdolist)来解决这个问题,特别是当你使用常见的lisp时,它不会# 39;强制要求编译器生成有效的代码,即使是尾递归调用。但话说回来,如果你不使用普通lisp的受限版本,你可以调用内置函数intersection。 : - )