如何写一个功能'重复'在Scheme中,返回一个应用于操作数n次的新函数

时间:2014-11-10 12:16:32

标签: scheme

我试图写一个功能'重复'在Scheme中作为理解lambdas的练习。

此函数将操作和数字作为参数,并返回将操作应用于操作数的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除以2三次,从n = 16开始,每次将操作应用于前一个结果。所以我们得到(/(/(/ 16 2)2)2)。

1 个答案:

答案 0 :(得分:1)

重复的第二个参数应该是一个函数(因为你调用(combop),但是你传递(操作操作数) repeat ,该函数使用操作数调用操作

(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 
    )
)

这不要求您更改重复的定义。或者,您可以采用Le Petit Prince's answer中的方法,并在重复的定义中将调用移至

在这两种情况下,你都使用本地定义,然后立即调用它,而且通常使用名为 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))))))