Lisp& rest参数和递归调用 [英] Lisp &rest parameters and recursive calls

查看:71
本文介绍了Lisp& rest参数和递归调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下Common Lisp函数:

I have the following Common Lisp Function:

(defun test(A &rest indexes)
  (if (null (first indexes))
      A
    (test (nth (+ 1 (first indexes)) A) (rest indexes))
  )
)

据我所知,& rest 参数在函数体中被视为列表,但由于

As far as I know &rest parameters are treated as a list in the function body but since

(其余索引)还会返回一个我被嵌套列表作为参数卡住的列表.

(rest indexes) also returns a list I'm stuck with nested Lists as parameters.

例如(test'(" a" b" c(" d" e))3 1 6 7)

将导致在第二次调用时索引为(((1 6 7)).

would cause indexes to be ((1 6 7)) at the second call.

有什么办法可以传递我的列表而不会出现此问题?

Is there any way to pass my list without having this problem?

推荐答案

rest 是访问器函数,与 first 配对使用,可以为您提供第一个元素和列表的其余部分. rest cdr 相同.

rest is a accessor function that is paired together with first to give you the first element and the rest of the list. rest is the same as cdr.

& rest lambda列表关键字,它将其余参数包含在其后的变量名中.

&rest is a lambda list keyword that slurps the remaining arguments in the variable name that follows it.

您确实在寻找 应用 .想象一下,我做了一个可以接受0个或多个数字参数并将它们加在一起的函数:

You are really looking for apply. Imagine I make a function that can take 0 or more numeric parameters and add them together:

(defun add (&rest numbers)
  (apply #'+ numbers))

Apply可以接受两个以上的参数.第一个是要调用的函数,除最后一个以外的所有参数都是放在最后一个arguments元素前面的额外参数.您可以确保该实现支持50个参数,或者在该特定实现中,函数可以接受的参数数量最多可以超过50个.

Apply can take more than two arguments. The first is the function to call and all but the last are extra arguments that are put in front of the last arguments element. You are guaranteed the implementation supports 50 arguments or upto the number of arguments a function can take in that particular implementation supports above 50.

(apply #'+ 1 2 '(3 4 5)) ; ==> 15

现在通过& rest apply 进行递归会使代码效率低下,因此您应该使用高阶函数,循环宏或创建助手:

Now recursing by &rest and apply makes inefficient code so you should use higher order functions, loop macro, or make a helper:

;; higher order function
(defun fetch-indexes (a &rest indexes)
  (mapcar (lambda (i) (nth i a)) indexes))

;; loop macro
(defun fetch-indexes (a &rest indexes)
  (loop :for i :in indexes
        :collect (nth i a)))

;; helper function
(defun fetch-indexes (a &rest indexes)
  (labels ((helper (indexes)
             (if (endp indexes)
                 '()
                 (cons (nth (first indexes) a)
                       (helper (rest indexes))))))
    (helper indexes)))

;; test (works the same with all)
(fetch-indexes '(a b c d) 2 3 0 1)
; ==> (c d a b)

应避免在递归中使用apply,但我将演示它是如何完成的.

Using apply in recursion should be avoided, but I'll show how it's done.

(defun fetch-indexes (a &rest indexes)
  (if (endp indexes)
      '()
      (cons (nth (first indexes) a)
            (apply #'fetch-indexes a (rest indexes)))))

在您的示例中,您具有嵌套列表.为了使其正常工作,您还需要将其展平.我还没有这样做,所以它们支持一个适当的元素列表.

In your example you have nested lists. In order for that to work you would need to flatten it as well. I haven't done that so these supports one proper list of elements.

这篇关于Lisp& rest参数和递归调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆