Common lisp 函数内变量的作用域

Common lisp 函数内变量的作用域,common-lisp,literals,Common Lisp,Literals,我写了一个函数,它返回小于20的数n的素因式分解。该函数使用let创建一个指数列表,并在发现n可被素数整除时增加这些指数 在我的Lisp解释器(gcl和clisp)中,当我调用下面的函数一次时,我得到了正确的因式分解,但当我第二次调用它时,我得到了第一个和第二个函数的因式分解之和-但指数的范围不限于let内部吗!?为什么不为指数重新分配值'(0 0 0 0 0 0 0 0 0 0)?如何重新编写此函数,使其能够承受多次调用 (setf primes '(2 3 5 7 11 13 17 19))

我写了一个函数,它返回小于20的数n的素因式分解。该函数使用let创建一个指数列表,并在发现n可被素数整除时增加这些指数

在我的Lisp解释器(gcl和clisp)中,当我调用下面的函数一次时,我得到了正确的因式分解,但当我第二次调用它时,我得到了第一个和第二个函数的因式分解之和-但
指数的范围不限于let内部吗!?为什么不为
指数
重新分配值
'(0 0 0 0 0 0 0 0 0 0)
?如何重新编写此函数,使其能够承受多次调用

(setf primes '(2 3 5 7 11 13 17 19))

(defun factorize (n)
  (let ((exponents '(0 0 0 0 0 0 0 0)))
    (loop for i from 0 to (- (length primes) 1) do
          (loop while (and (= (mod n (nth i primes)) 0) 
                           (not (= n 1))) do
            (incf (nth i exponents))
            (setf n (/ n (nth i primes)))))
    (return-from factorize exponents)))
输出:

>(factorize 10) ;; first time
(1 0 1 0 0 0 0 0) ;; 2^1*5*1 = 10, correct
>(factorize 10)
(2 0 2 0 0 0 0 0) ;; wrong
>(factorize 10)
(3 0 3 0 0 0 0 0)
列表“(0 0 0 0 0 0 0)存储为文本,修改文本是未定义的行为。你应该使用

(let ((exponents (copy-list '(0 0 0 0 0 0 0 0))))
在每次需要时复制文本,或者

 (let ((exponents (list 0 0 0 0 0 0 0 0)))
顺便说一句,使用

(defparameter *primes* '(2 3 5 7 11 13 17 19))
而不是在顶层设置f
。请注意,
*
符号是一种惯例,表示这是一个特殊变量。

列表(0 0 0 0 0 0 0 0 0)存储为文本,修改文本是未定义的行为。你应该使用

(let ((exponents (copy-list '(0 0 0 0 0 0 0 0))))
在每次需要时复制文本,或者

 (let ((exponents (list 0 0 0 0 0 0 0 0)))
顺便说一句,使用

(defparameter *primes* '(2 3 5 7 11 13 17 19))
而不是在顶层设置f
。请注意,
*
符号是一种惯例,表示这是一个特殊变量。

列表(0 0 0 0 0 0 0 0 0)存储为文本,修改文本是未定义的行为。你应该使用

(let ((exponents (copy-list '(0 0 0 0 0 0 0 0))))
在每次需要时复制文本,或者

 (let ((exponents (list 0 0 0 0 0 0 0 0)))
顺便说一句,使用

(defparameter *primes* '(2 3 5 7 11 13 17 19))
而不是在顶层设置f
。请注意,
*
符号是一种惯例,表示这是一个特殊变量。

列表(0 0 0 0 0 0 0 0 0)存储为文本,修改文本是未定义的行为。你应该使用

(let ((exponents (copy-list '(0 0 0 0 0 0 0 0))))
在每次需要时复制文本,或者

 (let ((exponents (list 0 0 0 0 0 0 0 0)))
顺便说一句,使用

(defparameter *primes* '(2 3 5 7 11 13 17 19))

而不是在顶层设置f。请注意
*
符号,这是一种惯例,表示这是一个特殊变量。

这只是另一个有趣的基于循环的解决方案,不涉及对列表的随机访问(效率相当低)。这还利用了,它返回一个商和一个余数作为多个值(您可以使用循环收集和分解)。由于您可以迭代素数,因此您只需收集指数即可:

(defparameter *primes* '(2 3 5 7 11 13 17 19))

(defun factorize (n)
  (loop
     for p in *primes* 
     collect (loop
                for (quotient remainder) = (multiple-value-list (truncate n p))
                while (zerop remainder)
                count (setf n quotient))))


当然,一旦你遍历一个列表并为每个值收集一个值,你就可以使用mapcar了。

这是另一个有趣的基于循环的解决方案,不涉及对列表的随机访问(这是相当低效的)。这还利用了,它返回一个商和一个余数作为多个值(您可以使用循环来收集和分解这些数据。由于您可以迭代素数,因此您只需收集指数即可:

(defparameter *primes* '(2 3 5 7 11 13 17 19))

(defun factorize (n)
  (loop
     for p in *primes* 
     collect (loop
                for (quotient remainder) = (multiple-value-list (truncate n p))
                while (zerop remainder)
                count (setf n quotient))))


当然,一旦你遍历一个列表并为每个值收集一个值,你就可以使用mapcar了。

这是另一个有趣的基于循环的解决方案,不涉及对列表的随机访问(这是相当低效的)。这还利用了,它返回一个商和一个余数作为多个值(您可以使用循环来收集和分解这些数据。由于您可以迭代素数,因此您只需收集指数即可:

(defparameter *primes* '(2 3 5 7 11 13 17 19))

(defun factorize (n)
  (loop
     for p in *primes* 
     collect (loop
                for (quotient remainder) = (multiple-value-list (truncate n p))
                while (zerop remainder)
                count (setf n quotient))))


当然,一旦你遍历一个列表并为每个值收集一个值,你就可以使用mapcar了。

这是另一个有趣的基于循环的解决方案,不涉及对列表的随机访问(这是相当低效的)。这还利用了,它返回一个商和一个余数作为多个值(您可以使用循环来收集和分解这些数据。由于您可以迭代素数,因此您只需收集指数即可:

(defparameter *primes* '(2 3 5 7 11 13 17 19))

(defun factorize (n)
  (loop
     for p in *primes* 
     collect (loop
                for (quotient remainder) = (multiple-value-list (truncate n p))
                while (zerop remainder)
                count (setf n quotient))))


当然,一旦你遍历一个列表并为每个值收集一个值,你就可以使用mapcar。

更好,因为指数的长度应该与素数的数量相同
(mapcar(经常为0)*primes*)
。不要在这里使用
返回。是的,循环构造
(返回指数)
会更清晰。除此之外,指数列表也可以是
(循环指数=…
。更好的是,因为指数的长度应该与素数
(mapcar(经常为0)*primes*)
)相同。并且不要在这里使用
返回。是的,循环结构最终是
(返回指数)
会更清晰。除此之外,指数列表也可以是
(循环指数=…
。更好的是,因为指数的长度应该与素数
(mapcar(经常为0)*primes*)
)相同。并且不要在这里使用
返回。是的,循环结构最终是
(返回指数)
会更清晰。除此之外,指数列表也可以是
(循环指数=…
。更好的是,因为指数的长度应该与素数
(mapcar(经常为0)*primes*)
)相同。并且不要在这里使用
返回。是的,循环结构最终是
(返回指数)
会更清晰。除此之外,指数列表可能是
(loop with exponents=…
。引用的数据是文字数据。如果您熟悉C,您可能会从代码中的文字字符数组中识别该行为。读取器会为您创建一个零的文字列表,该列表存储在编译代码中,因此您只有一个列表,并且它在函数的所有运行之间共享。Quoted数据是文字数据