将SICP解决方案从Scheme转换为Python

时间:2013-10-24 19:31:30

标签: python lisp scheme sicp

我在Lisp中有这个SICP代码的解决方案:

 ;; ex 1.11. Iterative implementation 

 (define (f n) 
   (define (iter a b c count) 
     (if (= count 0) 
       a 
       (iter b c (+ c (* 2 b) (* 3 a)) (- count 1)))) 
   (iter 0 1 2 n)) 

我真的不知道Lisp是如何工作的;我在这里理解了一些东西,但我仍然难以将其翻译成Python。例如,我不知道为什么a写在if之下。如何将此代码转换为Python或C ++? (该函数必须是迭代的而不是递归的)

3 个答案:

答案 0 :(得分:4)

有两种方法可以考虑翻译。一种是在不尊重Python的习语和惯例的情况下编写直译的文字 - 它看起来像这样:

def f(n):
    def iter(a, b, c, count):
        if count == 0:
            return a
        else:
            return iter(b, c, 2*b + 3*a + c, count-1)
    return iter(0, 1, 2, n)

另一种方法是以Pythonic方式编写代码,使其尊重目标语言的约定并利用其迭代机制:

def f(n):
    a, b, c = 0, 1, 2
    for count in range(n):
        a, b, c = b, c, 2*b + 3*a + c
    return a

顺便说一句,第二个版本会更快,并且不会出现堆栈溢出错误(Python 优化递归!)。在递归版本countn转到0并且循环版本count0转到n,这是无关紧要的,因为无论如何,除了迭代给定次数之外,count的值不被用于任何东西。

答案 1 :(得分:2)

我们来看看那段代码:

;; ex 1.11. Iterative implementation 

(define (f n) 
  (define (iter a b c count) 
    (if (= count 0) 
      a 
      (iter b c (+ c (* 2 b) (* 3 a)) (- count 1)))) 
  (iter 0 1 2 n)) 

首先要注意的是正在定义两个函数。一个是f,另一个是iteriter是辅助函数,仅供f使用(因为它在f里面定义了。没有理由你不能实际上,将这两个定义分为:

(define (iter a b c count) 
  (if (= count 0) 
    a 
    (iter b c (+ c (* 2 b) (* 3 a)) (- count 1))))

(define (f n) 
  (iter 0 1 2 n)) 

在Lisps中,语法(frob bar1 bar2 ...)表示您使用参数frobbar1bar2调用函数...。所以f

的定义
(define (f n) 
  (iter 0 1 2 n)) 

应该比较清楚。您定义的函数f只接受一个参数n,然后您使用四个参数[{1}},iter调用函数012。那么n做了什么?

iter

(define (iter a b c count) (if (= count 0) a (iter b c (+ c (* 2 b) (* 3 a)) (- count 1)))) 有四个参数。首先,它会检查iter是否为count。如果是,则0返回iter。否则,a会以iterb递归调用自己。 c(+ c (* 2 b) (* 3 a))以及递归调用返回的值。基于上面的Lisp语法描述,您应该能够告诉(- count 1)只是数学表达式 c + 2b + 3a ,而(+ c (* 2 b) (* 3 a))只是计数-1

我想,关于所有这一切最棘手的部分是知道(- count 1)有三个参数:第一个是测试表达式;第二个是“当时”部分,也称为结果;第三个是“其他”部分,也称为替代品。与if仅用于有条件地执行某些语句的其他语言不同,if在Lisp中返回,并且该值是结果的值或者替代值,取决于测试的值是真还是假。

通过此描述,您应该能够使用您熟悉的任何编程语言编写对应文件。

当然,一旦你理解了所有这些,你可能会读一些Chris Rathman's translation of SICP code into Python,其中包括练习1.11中代码的翻译:

(if ...)

答案 2 :(得分:1)

这基本上就是在C

中看起来如何
int iter (int a, int b, int c, int count)
{
    if( count == 0 )
       return a;
    else
       return iter(b, c, c + (2 * b) + (3 * a), count - 1);
}

Scheme中的每个表达式都计算为一个值,因此它是隐式返回。 if返回分支运行的任何内容,iter返回if返回的内容,依此类推。

不确定这看起来像一个递归序列,它引用前面的3个数字来计算在Scheme中迭代到常量堆栈的下一个数字。请注意,Python不会对尾部调用进行优化,并且C ++和C可能需要特殊的编译器选项和能够编译的编译器。