首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么‘Why’不能命名内部递归过程?

为什么‘Why’不能命名内部递归过程?
EN

Stack Overflow用户
提问于 2010-07-02 22:24:00
回答 3查看 907关注 0票数 3

考虑计算阶乘的函数的以下实现:

代码语言:javascript
复制
(define fac-tail
  (lambda (n)
    (define fac-tail-helper
      (lambda (n ac)
        (if (= 0 n)
            ac
            (fac-tail-helper (- n 1) (* n ac)))))
    (fac-tail-helper n 1)))

我试图用let重写内部定义:

代码语言:javascript
复制
(define fac-tail-2
  (lambda (n)
    (let ((fac-tail-helper-2
            (lambda (n ac)
              (if (= 0 n)
                  ac
                  (fac-tail-helper-2 (- n 1) (* n ac))))))
    (fac-tail-helper-2 n 1))))

define时没有错误,但是执行会导致:

代码语言:javascript
复制
#;> (fac-tail-2 4)
Error: undefined variable 'fac-tail-helper-2'.
{warning: printing of stack trace not supported}

如何使let版本工作?

方案版本为SISC v. 1.16.6

1基于factorial迭代版本在http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 1.2.1节中的应用

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-02 22:56:33

如何使let版本工作?

使用letrec而不是let

票数 8
EN

Stack Overflow用户

发布于 2010-07-02 22:30:26

R. Kent Dvbvig说:

实际上,let表达式是以lambda和过程应用程序定义的语法扩展,两者都是核心的语法形式。一般来说,表单的任何表达式

代码语言:javascript
复制
(let ((var expr) ...) body1 body2 ...) 

与以下内容相同。

代码语言:javascript
复制
((lambda (var ...) body1 body2 ...)
 expr ...)" [1]

这意味着fac-tail-2相当于:

代码语言:javascript
复制
(define fac-tail-2
  (lambda (n)
    ((lambda (fac-tail-helper-2)
       (fac-tail-helper-2 n 1)) ;; <== scope where fac-tail-helper-2 is visible.
     (lambda (n ac) ;; this lambda is assigned to fac-tail-helper-2
       (if (= 0 n)
           ac
           (fac-tail-helper-2 (- n 1) (* n ac))))))) ;; <=== problem

很明显,问题在于,fac-tail-helper-2名称在上面突出显示的lambda主体中作为参数可见,但不是分配给参数fac-tail-helper-2lambda中的名称。

1第2.5节,方案编程语言的"Lambda表达式“,第4版http://scheme.com/tspl4/start.html#SECTGSLAMBDA

票数 6
EN

Stack Overflow用户

发布于 2010-07-06 16:46:05

另外两个备选方案,为完整性而添加.

方案编程语言第4版第3.2节为使用let和递归函数提供了另外两种选择。http://scheme.com/tspl4/further.html#./further:h2

第一个是聪明的,不被推荐的。它包括向lambda添加一个参数,即它调用的lambda,然后传入它自己,以启动所有事情。

代码语言:javascript
复制
(define fac-tail-4
  (lambda (n)
    (let ((fac-tail-helper
            (lambda (fac-tail-helper n ac)
              (if (= 0 n)
                  ac
                  (fac-tail-helper fac-tail-helper (- n 1) (* n ac))))))
      (fac-tail-helper fac-tail-helper n 1))))

更简单的是命名为let,可以使用letrec的insead进行单次递归。

代码语言:javascript
复制
(define fac-tail-3
  (lambda (x)
    (let fac-tail-helper ((n x) (ac 1))
      (if (= 0 n)
          ac
          (fac-tail-helper (- n 1) (* n ac))))))

尽管该版本隐藏了一个隐式lambda定义,该定义被绑定到fac-tail-helper。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3169444

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档