【问题标题】:Recursively calling function in scheme with let使用 let 递归调用方案中的函数
【发布时间】:2020-01-19 17:43:09
【问题描述】:

是否有可能,在计划中,做类似以下的事情?

(define (foo a b c d e)
  (let ((recurse (foo a b c (bar d) e))
    (if (= d e)
        #f
        (recurse))))

我有一个函数,它有一组相当长的参数和一些递归调用它的条件,它相当难看,我希望能够简写它。

我已经尝试了几种不同的方法,但是我要么得到一个无限循环(我认为 let 正在热切地评估),要么我得到了严重的 let 表单错误。

【问题讨论】:

    标签: recursion scheme


    【解决方案1】:

    你需要一个重击:

    (define (foo a b c d e)
      (let ((recurse (lambda () (foo a b c (bar d) e))))
        (if (= d e)
            #f
            (recurse))))
    

    这允许您在部分但不是所有参数发生变化时添加参数。

    【讨论】:

    • 但这值得吗?为什么不只是保存价值? OP 的错误在于 let's 语法。
    • 不能只保存值,因为这会导致无限递归。代码必须有条件地运行,所以它必须用 thunk 延迟。
    • 成功了。我已经习惯了 Haskell 的完全懒惰的评估,我可以像 candy 一样撒上“where”子句而不去想它
    • 为什么要创建程序而不是仅使用(foo a b c (bar d) e) 作为替代方案?这没有任何意义。
    • @Sylwester 无限递归。如果没有延迟延迟,控制将永远不会到达停止在基本情况的条件。
    【解决方案2】:

    由于大多数参数没有改变,您应该考虑使用命名let

    (define (foo a b c d e)
      (let recurse ((d d))
        (if (= d e)
            #f
            (recurse (cdr d)))))
    

    这与以下基本相同:

    (define (foo a b c d e)
      (define (recurse d)
        (if (= d e)
            #f
            (recurse (cdr d))))
      // start recursion
      (recurse d))
    

    所有其他变量都可以通过闭包获得。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      • 2011-07-19
      • 2012-10-08
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多