为什么CLISP在此嵌套循环期间停止响应?

时间:2014-05-27 20:23:29

标签: lisp common-lisp

我正在尝试使用以下代码创建某些单词的子序列。当我添加by k时,代码停止响应,但如果我将k替换为特定数字,则可以正常工作。发生了什么事?

(let ((c nil)) (loop for k from 0 to (length "abc")
     finally (return c) do (loop for j from 0 to (length "abc") by k 
    do (loop for i from j to (length "abc") do (push (subseq "abc" j i) c))))) 

2 个答案:

答案 0 :(得分:4)

调试

  

如果我用特定的数字替换k,它就会起作用

如果将k替换为0会怎样?

如果您使用典型的约定格式化此代码会更有帮助,并且可能如果您将代码的特定部分隔离开来是有问题的。也就是说,(remove-duplicates …)不是问题所在,您可以删除它。使用一些更传统的格式和一些注释,您的代码是:

(remove-duplicates
 (let ((c nil))
   (loop for k from 0 to (length "abc")                  ; k starts at 0
      finally (return c) 
      do (loop for j from 0 to (length "abc") by k       ; looping for j from 0 to something by k
            do (loop for i from j to (length "abc")
                  do (push (subseq "abc" j i) c)))))
 :test 'equal)

如果您loop for j from 0尝试k任何事情,会发生什么?你几乎都在说,"从j开始为0,然后在下一次迭代时将其递增0 ..."所以j永远无处可去。这真的可能是printformat。我知道这与使用调试器不同,但有时最简单的方法是最快的:

[8]> (remove-duplicates
 (let ((c nil))
   (loop for k from 0 to (length "abc")
      finally (return c) 
      do (loop for j from 0 to (length "abc") by k 
            do
              (format t "~&k: ~a, j: ~a" k j )
              (loop for i from j to (length "abc")
                 do (push (subseq "abc" j i) c)))))
 :test 'equal)
k: 0, j: 0
k: 0, j: 0
k: 0, j: 0
…

收集子序列

如果您正在尝试收集给定序列的子序列,您可能会这样做。这适用于字符串(向量)和列表(尽管它对列表的效率较低)。

(defun subsequences (sequence) 
  (loop
     with length = (length sequence)
     for i from 0 to length
     nconcing (loop 
                 for j from (1+ i) to length
                 collecting (subseq sequence i j))))
(subsequences "abc")
;=> ("a" "ab" "abc" "b" "c")

(subsequences '(1 2 3))
;=> ((1) (1 2) (1 2 3) (2) (2 3) (3))


Appendex:来自SBCL的难以理解的错误

有趣的是,您会收到SBCL的运行时错误,尽管错误消息并未明确说明原因。也许它与无限循环有关。

* (remove-duplicates
 (let ((c nil))
   (loop for k from 0 to (length "abc")
      finally (return c) 
      do (loop for j from 0 to (length "abc") by k 
            do
              (loop for i from j to (length "abc")
                 do (push (subseq "abc" j i) c)))))
 :test 'equal)

debugger invoked on a TYPE-ERROR in thread #<THREAD "initial thread" RUNNING
                                              {1002978E71}>:
  The value 0
  is not of type
    (OR (SINGLE-FLOAT (0.0)) (DOUBLE-FLOAT (0.0d0)) (RATIONAL (0))).

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

答案 1 :(得分:1)

您认为BY 0应该在循环中做什么?

(loop for i from 0 upto 10 by 0 do (princ '*))

如果你没有推进变量,你将获得无限循环。