【问题标题】:Scheme: How do we write recursive procedure with lambda?方案:我们如何用 lambda 编写递归过程?
【发布时间】:2023-03-13 12:04:01
【问题描述】:

我正在阅读 Brain harvey 的计算机编程结构和解释。我遇到了这个问题,我不知道该怎么做。

我们如何在 Scheme 中用 lambda 编写递归过程?

【问题讨论】:

    标签: recursion lambda scheme sicp


    【解决方案1】:

    TL;DR:使用命名let(如果您正在立即执行递归函数)或rec(如果您要保存递归函数以供以后执行)。


    通常的方法是使用letrec,或者在幕后使用letrec,例如命名为letrec。这是使用letrec(factorial 10) 版本:

    (letrec ((factorial (lambda (x)
                          (if (< x 1) 1
                              (* (factorial (- x 1)) x)))))
      (factorial 10))
    

    同样的事情使用命名let:

    (let factorial ((x 10))
      (if (< x 1) 1
          (* (factorial (- x 1)) x)))
    

    这里的关键理解是两个版本完全相同。命名为let 只是一个扩展为letrec 形式的宏。因此,由于命名为 let 的版本较短,这通常是编写递归函数的首选方式。


    现在,您可能会问,如果您想直接返回递归函数对象,而不是执行它怎么办?在那里,你也可以使用letrec

    (letrec ((factorial (lambda (x)
                          (if (< x 1) 1
                              (* (factorial (- x 1)) x)))))
      factorial)
    

    这里也有一个简写,虽然没有使用命名let,而是使用rec

    (rec (factorial x)
      (if (< x 1) 1
          (* (factorial (- x 1)) x)))
    

    在这里使用rec 的好处是您可以将函数对象分配给一个变量并在以后执行它。

    (define my-fact (rec (factorial x)
                      (if (< x 1) 1
                          (* (factorial (- x 1)) x))))
    (my-fact 10)  ; => 3628800
    

    创建递归函数的更理论和“纯粹”的方法是使用Y combinator。 :-) 但是大多数实际的 Scheme 程序都没有使用这种方法,所以我不会进一步讨论。

    【讨论】:

      【解决方案2】:

      不需要写两次阶乘体;)

      (((lambda (f)
         (lambda (x)
           (f f x)))
       (lambda (fact x)
         (if (= x 0) 1 (* x (fact fact (- x 1)))))) 5)
      

      【讨论】:

        【解决方案3】:

        这是一个递归函数,使用 lambda 计算 5 的阶乘

        ((lambda (f x)
          (if (= x 0)
              1
              (* x (f f (- x 1)))))
         (lambda (f x)
          (if (= x 0)
              1
              (* x (f f (- x 1)))))
         5)
        

        当你在 Drracket 中运行这个程序时,你会得到 120 :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-10
          • 1970-01-01
          • 2010-10-30
          • 1970-01-01
          • 1970-01-01
          • 2011-10-31
          • 2014-06-22
          • 2021-08-17
          相关资源
          最近更新 更多