【问题标题】:How to write a function 'repeated' in Scheme that returns a new function applied to an operand n times如何在 Scheme 中编写一个“重复”函数,该函数返回一个应用于操作数 n 次的新函数
【发布时间】:2014-11-10 12:16:32
【问题描述】:

我正在尝试在 Scheme 中编写一个“重复”函数作为理解 lambdas 的练习。

此函数接受一个操作和一个数字作为参数,并返回一个 lambda,该 lambda 将该操作应用于操作数。

一个示例调用如下所示:

((repeated print 3) 'hello)
hello
hello
hello
=> "done"

这是我的尝试,但它不起作用,我花了将近一个小时挠头试图找出原因:

(define (repeated operation n)
    (lambda (operand)
        (define (repeat combop m)
            (if (= m 0)
                "done"
                (begin   
                    (combop)
                    (repeat combop (- m 1))
                )
            )
        )
        (repeat (operation operand) n)
    )
)

它返回这个

((repeated print 3) 'hello) 
hello
=> Error: #<undef> is not a function [(anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon), print, (anon), print, (anon), (anon), (anon), (anon), (anon), (anon), (anon), (anon)]

我的实现有什么错误?


感谢您的回答。

经过更多思考,我发现这里可能存在两个不同的问题,但我不清楚我要解决哪一个。

要重复相同的操作 n 次,一个正确的实现是这样的:

(define (do-n-times operation n)
    (if (= n 0)
        "done"
        (begin
            (operation)
            (do-n-times operation (- n 1))
        )
    )
)

运行示例:

(define (say-hello)
    (print 'hello)
)
(do-n-times say-hello 5)
hello
hello
hello
hello
hello
=> "done"

然而,一个不同的问题是连续地对一个属性应用一个变换,每次都将变换应用到前一个的结果。这是我实际上试图为其编写解决方案的问题。

所以解决方法如下:

要重复操作 n 次,每次使用结果作为操作的新操作数,示例实现可能如下所示:

(define (repeated operation n)
    (lambda (operand)
        (define (repeat operation result m)
            (if (= m 0)
                result
                (repeat operation (operation result) (- m 1))
            )
        )
        (repeat operation operand n)
    )
)

运行示例:

(define (divide-by-2 n)
    (/ n 2)
)
((repeated divide-by-2 3) 16)
=> 2

将 n 除以 3 次,从 n = 16 开始,每次将运算应用于前一个结果。所以我们得到 (/ (/ (/ 16 2) 2) 2)。

【问题讨论】:

  • 在写完“我不清楚我要解决哪个问题”之后,您描述了另一个相关问题。您真正想要解决的是哪一个
  • 我实际上是在尝试解决第二个示例,即重复应用于结果的操作。
  • 看来您已经找到了解决问题的方法,不是吗?
  • 是的,我最初发布了这个解决方案作为答案,但它被版主删除并合并到问题中。
  • 嗯,它并没有真正回答所提出的问题。也不清楚现在是否真的还有一个问题被问...现在一切都解决了吗,还是还有一个问题?

标签: scheme


【解决方案1】:

repeat 的第二个参数应该是一个函数(因为你调用了 (combop),但你传递的是 (operation operand)。解决此问题的最简单方法是首先使用 lambda 函数调用 repeat,该函数使用 operand 调用 operation

(define (repeated operation n)
    (lambda (operand)
        (define (repeat combop m)
            (if (= m 0)
                "done"
                (begin   
                    (combop)
                    (repeat combop (- m 1))
                )
            )
        )
        (repeat (lambda () (operation operand)) n) ; *** repeat with a function 
    )
)

这不需要您更改repeat 的定义。或者,您可以采用Le Petit Prince's answer 中的方法并将调用移到 repeat 的定义中。

在这两种情况下,您都在使用本地定义,然后立即调用它,并且通常使用命名为 let 更简洁地编写(使用我的答案和 Le Petit Prince 的答案):

(define (repeated operation n)
    (lambda (operand)
        (let repeat ((combop (lambda () (operation operand)))
                     (m n))
            (if (= m 0)
                "done"
                (begin   
                    (combop)
                    (repeat combop (- m 1)))))))

(define (repeated operation n)
  (lambda operand
    (let repeat ((m n))
      (when (positive? m)
        (apply operation operand)
        (repeat (- m 1))))))

【讨论】:

    猜你喜欢
    • 2012-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 2021-11-30
    • 2011-11-13
    • 1970-01-01
    相关资源
    最近更新 更多