【问题标题】:Is it possible to use call/cc to implement recursion?是否可以使用 call/cc 来实现递归?
【发布时间】:2012-04-12 21:29:19
【问题描述】:

我想知道是否可以定义一个递归函数而不在其主体中调用函数本身,而是以某种方式使用 call/cc 来代替?谢谢。

【问题讨论】:

    标签: functional-programming scheme callcc


    【解决方案1】:

    您可以使用call/ccas described here 实现 Y 组合器。 (非常感谢 John Cowan 提到这篇简洁的帖子!)引用该帖子,这是 Oleg 的实现:

    推论 1. 通过 call/cc 的 Y 组合器 -- 没有显式自应用的 Y 组合器。

    (define (Y f)
      ((lambda (u) (u (lambda (x) (lambda (n) ((f (u x)) n)))))
       (call/cc (call/cc (lambda (x) x)))))
    

    在这里,我们使用了一个事实

    ((lambda (u) (u p)) (call/cc call/cc))
    

    ((lambda (u) (u p)) (lambda (x) (x x)))
    

    在观察上是等效的。

    【讨论】:

    • 太棒了,正是我想要的。非常感谢。
    • @wberry 我决定找到一种方法来引用该代码 sn-p,希望它更符合“合理使用”标准。
    【解决方案2】:

    你的问题有点含糊。特别是,听起来您想要一个使用 call/cc 来模拟递归调用而不直接进行递归调用的系统。然而,事实证明,您可以在不进行递归调用的情况下对递归调用进行建模,在不使用 call/cc 的情况下进行建模。例如:

    #lang racket
    
    (define (factorial f n)
      (if (= n 0) 1 (* n (f f (- n 1)))))
    
    (factorial factorial 3)
    

    这看起来像是作弊,但它是 Y 组合器的基础。也许您可以收紧您正在考虑的一系列限制?

    P.S.:如果这是作业,请引用我!

    【讨论】:

    • 嗯,我已经知道这个技巧来做递归了。我想知道是否存在使用 call/cc 的非自引用方式来定义递归函数,比如你的factorial。这不是家庭作业!谢谢。
    • @plmday John 的解决方案已经不是自引用的。您还需要call/cc 提供什么?
    • @SamTobin-Hochstadt 好吧​​,f 指的是它自己,不是吗?我想看看call/cc 能走多远,特别是考虑到它的能力,我们能不能用它来模拟定义递归函数的常用或不寻常的方式。
    • “引用自身”是什么意思? (自)递归函数定义中的自引用具有这种形式:您有一个函数定义,其主体包含一个标识符,该标识符在词法上绑定到封闭函数本身。 John 提供的factorial 的定义没有出现在正文中的factorial,也没有任何在词法上绑定到它的标识符。
    • 啊,好吧,你是对的。我将它与自我申请混合在一起。感谢您的澄清。
    【解决方案3】:

    恐怕call/cc 与此无关。实际上只有两种定义递归函数的方法:

    • 假设您的语言允许递归函数定义;即,函数体可以引用封闭函数,或者函数体f 可以引用函数g,其主体引用f。在这种情况下,您只需按照通常的方式编写即可。
    • 如果您的语言禁止这两种方法,但它仍然具有一流的函数和 lambda,那么您可以使用 fixed-point combinator,如 Y 组合器。您编写函数,以便将一个用于表示递归步骤的函数作为额外参数;您将递归的每个地方,而不是调用该参数。

    所以对于factorial,你可以这样写:

    (define (factorial-step recurse n)
      (if (zero? n)
          1
          (* n (recurse (- n 1)))))
    

    Y 组合器的神奇之处在于它构造了recurse 函数,该函数将被馈送到factorial-step

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 2014-09-02
      • 2012-01-22
      • 2012-11-05
      • 1970-01-01
      相关资源
      最近更新 更多