gpt4 book ai didi

list - 在 Common Lisp 中创建升序数字列表

转载 作者:行者123 更新时间:2023-12-03 07:55:44 28 4
gpt4 key购买 nike

我只想用c-lisp编写一个简单的程序;接受一个数字并返回从 0 到该数字的所有数字的列表。我对 lisp 比较陌生,我很好奇更有经验的人会如何做到这一点。我的程序是这样的:

(let ((a 0) (lis '())) 
(defun counter (len)
(setq lis (cons a lis)) (setq a (+ a 1))
(if (< a len) (counter len) lis)
))

但我觉得它不太符合 lisp 的精神,一定有更优雅的方法吧?

我的另一个想法是这个的某个版本,但是如何将输出放入列表中?

(defun counter2 (x) 
(print x)
(cond ((< 0 x) (counter2 (- x 1)))))

感谢您的时间和最终的帮助,:)

最佳答案

我们将研究一系列转换,尝试改进您的代码:

您的代码:

(let ((a 0) (lis '())) 
(defun counter (len)
(setq lis (cons a lis)) (setq a (+ a 1))
(if (< a len) (counter len) lis)
))

格式

典型的格式如下:

(let ((a 0)
(list '()))
(defun counter (len)
(setq list (cons a list))
(setq a (+ a 1))
(if (< a len)
(counter len)
list)))

问题

上面的代码有很多问题:

  • 函数定义周围有一个LET。这在函数外部定义了变量alist?为什么?

  • 看起来非常有必要

  • 这是一个递归函数,可能会耗尽堆栈空间

  • 不返回按升序排列的数字列表,这是问题陈述中的要求

更好的递归版本

让我们看一下递归版本:

(defun counter (len &optional (a 0) (list '())) 
(if (>= a len)
list
(counter len
(1+ a)
(cons a list))))

上面去掉了周围的LET并使变量alist成为可选参数。

基本情况也是 IF 中的 then 情况。

隐藏变量alist可能会更好。所以我们可以使用局部递归函数:

(defun counter (len)
(labels ((counter-rec (a list)
(if (>= a len)
list
(counter-rec (1+ a) (cons a list)))))
(counter-rec 0 '())))

上述函数使用本地函数进行递归。

我们仍然可能希望按升序返回列表:

(defun counter (len)
(labels ((counter-rec (a list)
(if (>= a len)
list
(counter-rec (1+ a) (cons a list)))))
(nreverse
(counter-rec 0 '()))))

上面使用了破坏性函数NREVERSE,我们可以使用它,因为生成的列表是新创建的并且没有在其他地方使用。

我们还可以在递归函数中进行倒数。这摆脱了NREVERSE:

(defun counter (len)
(labels ((counter-rec (a list)
(if (minusp a)
list
(counter-rec (1- a) (cons a list)))))
(counter-rec (1- len) '())))

将 DO 循环用于非递归版本

(defun counter (len)
(do* ((a len (1- a))
(list '() (cons a list)))
((zerop a) list)))

(defun counter (len)
(do* ((a len (1- a)) ; A from len to zero
(list '() (cons a list))) ; consing the result
((zerop a) list))) ; the end condition and
; list as the result

循环

Common Lisp 提供了一个内置的强大的 LOOP 宏,我们可以这样写:

(defun counter (len)
(loop for i below len
collect i))

上面从 0 迭代 i(1- len) 并将每个 i 收集到一个列表中返回。

COUNTER 在 Lisp 中称为 IOTA

COUNTER 这样的函数存在于 Lisp 库中,传统上称为 iota

CL-USER 1 > (ql:quickload "alexandria")
("alexandria")

CL-USER 2 > (apropos "iota")
ALEXANDRIA:MAP-IOTA (defined)
ALEXANDRIA:IOTA (defined)

CL-USER 3 > (ALEXANDRIA:IOTA 10)
(0 1 2 3 4 5 6 7 8 9)

关于list - 在 Common Lisp 中创建升序数字列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76076952/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com