2012-04-17 50 views
9
(do ((n 0 (1+ n)) 
    (cur 0 next) 
    (next 1 (+ cur next))) 
    ((= 10 n) cur))) 

这是关于关键字Lisp的教科书的例子“做”了解Common Lisp的做宏观语法

的“做”的基本模板是:

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

但是,在这个例子中,它是不清楚哪个部分是哪个。而且,中间两条线是做什么的?

谢谢!

+3

AFAIR,“do”是一个宏。 – zvrba 2012-04-17 06:07:31

回答

8

你的好缩进清楚地显示这部分是:

(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没有出现第三个参数:没有S的身体评论(空循环)。

23
(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 Fibonacci数


可选EBNF /形式化语法:

根据的语法是:

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

理解,这需要的Hyperspec

+1

显示C翻译的好主意,用'old_' vars来模拟并行分配!只是为了整洁:你的Lisp代码是错误对齐的,并有一个额外的右括号;你的C代码缺少结尾分号。 :) – 2012-04-25 16:55:28

+0

看这个翻译,说do do宏更像命令式编程,而不是函数式编程吗? – 2012-09-02 16:45:13

+1

@hyh yes和no ---通用lisp是多范例,这是一个迭代构造,它更新变量,这当然是必要的。然而这个形式返回一个值,所以你可以使用这个循环作为返回值,或者作为if语句中的一个条件(例如'(if(>(this-fib-loop)10)'gt-10'lte-10 )''这是更多的功能 – tobyodavies 2012-09-02 23:48:46

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

EBNF知识和大块做了3部分。

  1. 可变
  2. 终止条件

在这个特定的示例中,存在没有身体。所有真正的工作完成1.和2.首先它设置3个变量,并给出初始值和步骤形式。例如。 n设置为0,在每次迭代期间它步骤还:(1+ n)将递增n

的终止条件是((= n 10) cur):当n等于10。然后返回cur因为这do表达的整个返回值。

结合所有这些,在这个do例如,它会从1相加为10,得到55

+2

它的'结果形式n'而不是'行动n'您的第二个代码块也严重缩进。 – tobyodavies 2012-04-17 06:08:18

+1

你错过了许多括号。此外,它计算序列'(cur,next)=(0,1)(1,1)(1,2)(2,3)(3,5)(5,8)(8,13).. 。斐波那契数字,不只是部分总和。 – 2012-04-25 16:59:57

+0

@tobyodavies你是对的。我的错。 – juanitofatas 2012-06-14 23:55:30