为什么 `-` 参数顺序会导致 Racket REPL 运行 内存不足?

Why does `-` parameter order cause Racket REPL to run out of memory?

我在将参数顺序交换到 - 函数时遇到问题。

; source

(define (compose f g) (lambda (x) (f (g x))))

(define (repeated f n)
  (if (= n 1)
    f
    (compose f (repeated f (- 1 n))) ; causes an out of memory error
    (compose f (repeated f (- n 1))) ; runs without issue
))

(define (square n) (* n n))
((repeated square 2) 6) ; 1296


; REPL

> > Racket virtual machine has run out of memory; aborting
Aborted (core dumped)

如果我对值进行硬编码,问题就会出现。此外,如果我使用 +.

递增 n,则该问题不适用

当你开始时 n2,然后你调用 (repeated f (- 1 2))(- 1 2)-1,不等于1,所以继续(repeated f (- 1 -1))(- 1 -1) 是 2,所以你再次调用 (repeated f 2) 就进入了死循环。

当使用其他顺序时,您从 (- 2 1) 开始,即 1,因此这就是递归停止的地方。

换句话说:如果您从大于 1 的数字开始,并且不断从 n 中减去 1,您最终将达到 1 并且递归将停止。如果您改为从 1 中减去 n,您将进入一个循环并且递归将永远继续(或者更确切地说,直到您 运行 内存不足)。

加法不会出现同样的问题,因为加法是可交换的。也就是说,将 x 添加到 y 并将 y 添加到 x 会产生完全相同的结果。减法则不然。