【问题标题】:Why does my Common Lisp loop only work on trivial code?为什么我的 Common Lisp 循环只适用于琐碎的代码?
【发布时间】:2011-11-06 13:52:54
【问题描述】:

我有一点代码:

(defun divisor (x)
  (loop for i from 2 to x do
       (if (= x i) (return x) 
           (if (not (mod x i))
               (return (append i (divisor (/ x i))))))))

应该返回 x 的主要因子列表。但是,代码只返回 x。

defun 的评估没有错误。我试图跟踪 defun 中的每个函数,但没有一个被评估过。循环是一个宏,所以我无法追踪它,但是如果我清除循环内部并替换为

(format t "~d " i)

如我所料,它从 2 计数到 x。

我认为我做错了什么,但我想不通。

【问题讨论】:

    标签: loops for-loop lisp common-lisp


    【解决方案1】:

    一个问题是您使用(not (mod x i)) 来确定@​​987654322@ 评估是否为0,这是错误的。

    另一个问题是您将原子附加到列表中,我认为这不是您想要做的。

    这是一个似乎可行的修订版:

    (defun divisor (x)
      (loop for i from 2 to x do
           (if (= x i) (return (list x))
               (if (= (mod x i) 0)
                   (return (append (list i) (divisor (/ x i))))))))
    

    【讨论】:

    • (not (mod x i)) 不起作用的原因是,在 common lisp(包括 0)中,除了 nil 之外的任何东西都是正确的。此外, (cons i (divisor (/ x i)) 可能更简洁一些,更接近 Albertus 的意图。
    • 谢谢,我没有意识到 0 不是 nil。此外,附加显然需要列表,而不是原子。 @Daan你是对的,缺点绝对是我正在寻找的。谢谢!
    【解决方案2】:

    在你的循环中,我最终到达了 x。然后你返回 x,丢弃你可能从子递归返回的任何其他返回值。

    我认为您错误地将循环与递归结合在一起。您只需要执行其中一项即可。

    【讨论】:

      【解决方案3】:
          (defun divisor (x) 
            (loop for i from 2 to x when (eql 0 (mod x i)) collect i))
      

      【讨论】:

      • OP 似乎需要素数分解(例如,12 -> 2, 2, 3),而此函数返回所有不同的因子(12 -> 2, 3, 4, 6);完全不同。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 2013-05-16
      相关资源
      最近更新 更多