4

我正在尝试将此 Python 代码转换为 Common Lisp:

for a in xrange(1,1000):
    for b in xrange(a,1000):
        c = (a**2 + b**2) ** 0.5
        s = a + b + c
        if s == 1000:
            return a * b * c

我的第一次尝试是:

(loop for a from 1 to 999
      do (loop for b from a to 999
               for c = (sqrt (+ (expt a 2) (expt b 2)))
               for s = (+ a b c)
               until (= s 1000)
               finally return (* a b c))))

这行不通。我的任务是:当s点击 1000 时,使上面的整个表达式返回(* a b c)。如何从嵌套循环宏中返回一些值?

4

3 回答 3

11

可以使用blockandreturn-from操作符:block建立一个命名的代码块,你可以return-from使用该块的名称从这个块返回

(let (c s)
  (block nested-loops
    (do ((a 1 (1+ a))) ((= a 999))
      (do ((b a (1+ b))) ((= b 999))
        (setf c (sqrt (+ (expt a 2) (expt b 2)))
              s (+ a b c))
        (if (= s 1000)
            (return-from nested-loops (* a b c)))))))

PS,我loop这里没用过,只是习惯了do

也来自http://www.gigamonkeys.com/book/loop-for-black-belts.html

要允许使用 RETURN-FROM 从特定循环返回(在嵌套 LOOP 表达式时很有用),您可以使用命名的循环关键字命名 LOOP。如果命名子句出现在循环中,它必须是第一个子句。举个简单的例子,假设列表是一个列表列表,并且您希望在其中一个嵌套列表中找到与某些条件匹配的项目。你可以通过一对这样的嵌套循环找到它:

(loop named outer for list in lists do
     (loop for item in list do
          (if (what-i-am-looking-for-p item)
            (return-from outer item))))
于 2012-12-25T07:29:22.393 回答
8

Pythonreturn语句不会从循环中返回,它会从包含循环的整个函数中返回。在 Common Lisp 中,函数会建立一个与函数同名的隐式块。所以你可以使用:

(return-from function-name (* a b c))

执行与 Python 代码等效的返回。

于 2012-12-25T08:52:23.317 回答
1

我认为您的解决方案应该在尝试保持 python 代码的原始形式的同时进行少量调整

(loop named outer for a from 1 below 1000 do
 (loop for b from a below 1000
    for c = (sqrt (+ (expt a 2) (expt b 2)))
    for s = (+ a b c)
    if (= s 1000) do (return-from outer (* a b c))))

如果你想输入中缀方程,你可以使用 quicklisp 提供的中缀库和 (ql:quickload :infix),然后修改上面得到

(loop named outer for a from 1 below 1000 do
 (loop for b from a below 1000
    for c = #i(sqrt (a^^2 + b^^2))
    for s = #i(a + b + c)
    if (= s 1000) do (return-from outer #i(a * b * c))))
于 2013-12-18T14:48:59.957 回答