Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Common Lisp:如果与setf+相同,则为delete;如果删除?_Lisp_Common Lisp_Primes - Fatal编程技术网

Common Lisp:如果与setf+相同,则为delete;如果删除?

Common Lisp:如果与setf+相同,则为delete;如果删除?,lisp,common-lisp,primes,Lisp,Common Lisp,Primes,以下代码生成从1到n的素数: (defun prime-list(n) (let ((a)(b)(x (floor (sqrt n)))) (loop for i from (floor n 6) downto 1 do (push (1+ (* 6 i)) a) (push (1- (* 6 i)) a)) (loop while (<= (car a) x) do (push (car a) b)

以下代码生成从1到n的素数:

(defun prime-list(n)
  (let ((a)(b)(x (floor (sqrt n))))
    (loop for i from (floor n 6) downto 1 do
          (push (1+ (* 6 i)) a)
          (push (1- (* 6 i)) a))
    (loop while (<= (car a) x) do
          (push (car a) b)
          (setf a (remove-if #'(lambda(m)(or (= 0 (mod m (car a))) (> m n))) a)))
    (append '(2 3) (reverse b) a)))
可以用

(delete-if #'XXX a)

我希望这能让它更快。然而,当我做出更改时,函数现在进入一个无限循环,永远不会返回。为什么?

我没有很多CL经验,但我在Scheme方面做了很多工作

在第二个版本(sans setf a)中,将计算remove if表达式,但它不会实际更改a。loop是CL中的一个宏,它只计算表达式,但不像递归函数那样使用这些表达式的结果

因此,在第一个版本中,由于setf,每次循环运行时,a的值都会更改,但在第二个版本中,a的值始终保持不变。因此(a车)永远不会改变,循环也永远不会终止

我们可以在两个循环语句上比较macroexpand的结果:

没有setf:

(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
 (BLOCK NIL
  (LET NIL
   (MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
    (TAGBODY SYSTEM::BEGIN-LOOP
     (PROGN (UNLESS (< (CAR A) X) (LOOP-FINISH))
      (PROGN (PUSH (CAR A) B) (REMOVE-IF #'(LAMBDA (M) (= 0 (MOD M (CAR A)))) A)))
     (GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
     (MACROLET
      ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP))))))))) ;
(MACROLET((LOOP-FINISH NIL(系统::LOOP-FINISH-ERROR)))
(零区)
(零
(MACROLET((循环-完成零’(GO系统::结束-循环)))
(标记体系统::BEGIN-LOOP
(程序(除非(<(车辆A)X)(环加工))
(程序(推动(车辆A)B)(移除-IF(λ(M)(=0(模块M(车辆A)))A)))
(GO系统::开始循环)系统::结束循环
(MACROLET)
((循环结束零(系统::循环结束警告);(GO系统::结束循环()()()()()));
使用setf:

(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
 (BLOCK NIL
  (LET NIL
   (MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
    (TAGBODY SYSTEM::BEGIN-LOOP
     (PROGN (UNLESS (< (CAR A) X) (LOOP-FINISH))
      (PROGN (PUSH (CAR A) B)
       (SETF A (REMOVE-IF #'(LAMBDA (M) (= 0 (MOD M (CAR A))))) A)))
     (GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
     (MACROLET
      ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP))))))))) ;
(MACROLET((LOOP-FINISH NIL(系统::LOOP-FINISH-ERROR)))
(零区)
(零
(MACROLET((循环-完成零’(GO系统::结束-循环)))
(标记体系统::BEGIN-LOOP
(程序(除非(<(车辆A)X)(环加工))
(程序(推动(轿厢A)B)
(设定值A(移除-IF#’(LAMBDA(M)(=0(MOD M(CAR A‘‘‘‘)’)A)))
(GO系统::开始循环)系统::结束循环
(MACROLET)
((循环结束零(系统::循环结束警告);(GO系统::结束循环()()()()()));
您可以看到,在第一个循环中,remove if表达式被计算,但它的结果没有被使用。

Chris是正确的


使用
delete if
代替
remove if

可以加快速度。如注释中所述,您需要设置变量

DELETE-IF
主要是
REMOVE-IF
的破坏性版本
REMOVE-IF
返回新使用的序列,该序列不包含已删除的元素
DELETE-IF
可能返回重复使用的序列


如果您有一个绑定到列表的变量,则仍然需要设置结果。上面的函数返回结果,但它们不为结果设置变量。在列表的情况下,
DELETE-IF
操作的结果可以是空列表,并且当它指向非空列表时,不可能有副作用,可以为它设置一个变量。

Oops,我想我问错了问题,我的意思是“
(setf a(remove IF#XXX a))
可以被
(delete if#'xxxa)
“对不起,我想问一下delete if(我在标题中写了delete if),我发现delete if不起作用。我正在使用Lispworks,当我尝试delete if时,发生了一些非常奇怪的事情:delete if不会删除第一个条目,即使第一个条目应该被删除。请看,您仍然需要使用
setf
(setf foo(delete if#some-pred foo))
。您仍然需要
(setq a(delete if…)
此外,当第一个元素需要删除时,返回的值将始终与原始序列不同(没有明智的方法可以通过外科手术删除列表中的第一个cons,同时仍然有指向该cons的指针,因此返回第一个未删除的cons)。错误1:应该是
while(还有,这是一个试除法筛子,它的效率比埃拉托斯提尼筛子低得多(它以相等的增量进行计数以找到倍数,而不是通过除法进行测试)。@WillNess-True。我在玩这个,没有考虑效率。后来我使用了位数组,你可以在这里找到代码:(第二个。欢迎评论。)明白。我只是为了一个普通读者的利益才注意到这一点。(错误1现在已经修复;错误2仍然存在)。@WillNess改变了。但这可能不是修复它的最佳方式。。)
(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
 (BLOCK NIL
  (LET NIL
   (MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
    (TAGBODY SYSTEM::BEGIN-LOOP
     (PROGN (UNLESS (< (CAR A) X) (LOOP-FINISH))
      (PROGN (PUSH (CAR A) B)
       (SETF A (REMOVE-IF #'(LAMBDA (M) (= 0 (MOD M (CAR A))))) A)))
     (GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
     (MACROLET
      ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP))))))))) ;