理解 Common Lisp do 宏语法

问题描述 投票:0回答:4
(do ((n 0 (1+ n))
     (cur 0 next)
     (next 1 (+ cur next)))
    ((= 10 n) cur)))

这是 Lisp 教科书中关于关键字“do”的示例

“做”的基本模板是:

(do (variable-definitions*)
    (end-test-form result-form*)
 statement*)

但是,对于这个例子,我不清楚哪一部分是哪一部分。还有,中间的两行是做什么的?

谢谢!

lisp iteration common-lisp
4个回答
30
投票
(do ((n 0 (1+ n))  ;declares n, initially 0, n+1 each subsequent iteration)
     (cur 0 next)   ;declares cur, initially 0, then old value of next
     (next 1 (+ cur next))) ;declares next, initially 1, then the sum of (the old) cur and next
    ((= 10 n) ;end condition (ends when n = 10)
     cur)    ; return value
  ;empty body
  )

翻译成类似c的代码

for(n=0, cur=0, next=1 ;
    !(n == 10) ;
    n=old_n+1, cur=old_next, next = old_cur + old_next)
{
    //do nothing 
    old_n = n;
    old_cur = cur;
    old_next = next;
}
return cur;

顺便说一句,您应该能够看到此代码返回第 10 个斐波那契数


可选的 EBNF/形式语法:

根据Hyperspec的语法是:

(do ({var | (var [init-form [step-form]])}*) 
    (end-test-form result-form*) 
    declaration* 
    {tag | statement}*)

理解这一点需要了解 EBNF 和大量的 Hyperspec


14
投票

您良好的缩进清楚地显示了哪个部分是哪个:

(do ((n 0 (1+ n))
    ^(cur 0 next)
    |(next 1 (+ cur next)))
    |
    +-- first argument of do

    ((= 10 n) cur)))
    ^
    |
    +-- start of second argument of do

看,它们排列得很好,而且内部材料是凹进的:

   ((n 0 (1+ n))
    (cur 0 next)
    (next 1 (+ cur next)))
    ^
    |
    +- inner material of argument: three forms which are
       indented by 1 character and aligned together.

你的

do
那里没有第三个参数:没有语句体(空循环)。


1
投票

有时,它可以帮助 1. 用注释对表单进行注释,2. 打印正文中的当前值,如下所示:

(do
 ;; varlist
 ((n 0 (1+ n))
  (cur 0 next)
  (next 1 (+ cur next)))
 ;; endlist
 ((= 10 n) cur)
  ;; body
  (print (list n cur next)))

此打印

(0 0 1) 
(1 1 1) 
(2 1 2) 
(3 2 3) 
(4 3 5) 
(5 5 8) 
(6 8 13) 
(7 13 21) 
(8 21 34) 
(9 34 55) 
55

这应该可以解决问题。 @_@


0
投票
(do ((n 0 (1+ n))
     (cur 0 next)
     (next 1 (+ cur next)))
    ((= 10 n) cur))

do 有 3 部分。

  1. 变量
  2. 终止条件
  3. 身体

在这个特定的例子中没有身体。所有实际工作均由 1. 和 2. 完成。首先,它设置 3 个变量并给出初始值和步骤形式。例如。

n
设置为 0,并在每次迭代期间进一步进行:
(1+ n)
,这将增加
n

终止条件为

((= n 10) cur)
:当
n
等于 10 时。然后返回
cur
作为此
do
表达式的整个返回值。

将所有这些结合起来,在这个

do
示例中,它将从 1 到 10 相加,得到 55

© www.soinside.com 2019 - 2024. All rights reserved.