Functional programming LISP函数打印出最多N个数字的斐波那契序列

Functional programming LISP函数打印出最多N个数字的斐波那契序列,functional-programming,lisp,common-lisp,Functional Programming,Lisp,Common Lisp,我必须编写代码来计算N个斐波那契数(其中N是函数参数)。我是LISP新手,正在努力学习语法。这就是我目前所拥有的。。。我觉得很接近 (defun fib (n) (if (or (= n 1) (= n 2)) (print 1)) (print (+ (fib (- n 1))(fib (- n 2))))) ;;;;It should output like so: (fib 0) () (fib 2) ( 1 1 ) (fib 6) ( 1 1 2 3 5 8 ) 有人能帮我整理一下我的

我必须编写代码来计算N个斐波那契数(其中N是函数参数)。我是LISP新手,正在努力学习语法。这就是我目前所拥有的。。。我觉得很接近

(defun fib (n)
(if (or (= n 1) (= n 2))
(print 1))
(print (+ (fib (- n 1))(fib (- n 2)))))
;;;;It should output like so:
(fib 0)
()
(fib 2)
( 1 1 )
(fib 6)
( 1 1 2 3 5 8 )

有人能帮我整理一下我的功能,让它正常工作吗?提前谢谢

您的操作方式是这样的,它的运行时间将呈指数级增长。这种联系有有效的替代办法。但是,如果你想保留整个序列,你可以这样做

(defun fib (num)
  (let (seq)
    (labels ((helper (n)                                  ; define local helper function
               (when (<= n num)                           ; stop when reached NUM
                 (if (< n 3) (push 1 seq)
                     (push (+ (car seq) (cadr seq)) seq)) ; sum of previous 2
                 (helper (1+ n)))))                       ; recurse
      (helper 1))                                         ; start from first fib number
    (nreverse seq)))                                      ; reverse the result
(定义fib(num)
(续)
标签((辅助对象(n);定义局部辅助对象函数
(当(如果您希望从REPL中的评估
(fib 2)
中得到
(1 1)
,那么您不希望打印任何内容,只希望返回列表
(1)

使用递归。 (除纤(限值) (标签((辅助对象)(n a b) (如果(>n限值) '() (cons a(helper(1+n)b(a b(()))) (帮助程序0 1))) 使用尾部递归。通常在 已编译,但这不是标准中的要求。 (除纤(限值) (标签((辅助对象)(n a b acc) (如果(>n限值) (附件一) (助手(1+n)b(+a b)(cons a acc(()()))) (帮助程序0 1’())) 使用循环。从不吹堆栈。 (除纤(限值) (循环:对于a:=0:b :和b:=1:然后(+ab) :重复限制 :收集
我认为所有这些都具有同样的可读性,因此没有理由不选择在任何实现中最安全的
循环
版本


请注意,第一个数字是0,我的代码反映了这一点。

这里是另一种方法,您可以使用带有延续的辅助过程来解决问题

此过程是尾部递归的,但不需要反转斐波那契数的累积列表

(define (fib n)
  (define (aux n a b k)
    (if (zero? n)
        (k (list a))
        (aux (sub1 n)
             b
             (+ a b)
             (lambda (rest) (k (cons a rest))))))
  (aux n 0 1 identity))

(fib 0)  ;; => '(0)
(fib 1)  ;; => '(0 1)
(fib 2)  ;; => '(0 1 1)
(fib 10) ;; => '(0 1 1 2 3 5 8 13 21 34 55)

这里的代码是racket,但您可以相对轻松地将其转换为Lisp。

一个问题:您将属于
if
的一个括号放错了位置。在该
循环中,如果您使用
:和
执行并行步进,则不需要
tmpa
:对于n:upto limit
也可以更清晰地显示为
:repeat limit
@Svante我知道
:repeat
但是
:和
我以前从未使用过,因此学到了一些新东西。谢谢:-)