内外还原,结果一样吗?

inner and outer reduction, same result?

内缩减和外缩减是否总是产生相同的值,如果不是,会导致不同的值吗?

我说的是 Racket,一种函数式语言。

我知道有可能它在 Racket 中更有效,但实际上会导致不同的结果。我无法创建发生这种情况的案例,但我觉得这应该是可能的,而且可能是。不知道很危险。

示例:

;inner reduction
    (sqr (* 3 (+ 1 (sqr 2))))
        ->(sqr (* 3 (+ 1 (* 2 2))) ;(sqr)
        ->(sqr (* 3 (+ 1 4)) ;(*)
        ->(sqr (* 3 5)) ;(+)
        ->(sqr 15) ;(*)
        ->(* 15 15) ;(sqr)
        ->225 ;(*)

;outer reduction
    (sqr (* 3 (+ 1 (sqr 2))))
        ->(* (* 3 (+ 1 (sqr 2))) (* 3 (+ 1 (sqr 2))) ;(sqr)
        ->(* (* 3 (+ 1 (* 2 2))) (* 3 (+ 1 (sqr 2))) ;(sqr)
        ->(* (* 3 (+ 1 4)) (* 3 (+ 1 (sqr 2))) ;(*)
        ->(* (* 3 5) (* 3 (+ 1 (sqr 2))) ;(+)
        ->(* 15 (* 3 (+ 1 (sqr 2))) ;(*)
        ->(* 15 (* 3 (+ 1 (* 2 2))) ;(sqr)
        ->(* 15 (* 3 (+ 1 4))) ;(*)
        ->(* 15 (* 3 5)) ;(+)
        ->(* 15 15) ;(*)
        ->225 ;(*)

我不了解 Racket,但一般来说,如果您的任何表达式有副作用,例如修改变量、执行 input/output 等,您可能 运行 会遇到麻烦

举个例子:

(define x 1)
(sqr (begin (set! x (add1 x)) x))

内减:

; x = 1
(sqr (begin (set! x (add1 x)) x))

; x = 2
(sqr (begin x))

; x = 2
(sqr (begin 2))

; x = 2
(sqr 2)

; x = 2
(* 2 2)

; x = 2
4

即结果是 4x 的最终值是 2.

通过外部归约,你得到:

; x = 1
(* (begin (set! x (add1 x)) x)
   (begin (set! x (add1 x)) x))

; x = 2
(* (begin x)
   (begin (set! x (add1 x)) x))

; x = 2
(* 2
   (begin (set! x (add1 x)) x))

; x = 3
(* 2
   (begin x))

; x = 3
(* 2
   (begin x))

; x = 3
(* 2
   3)

; x = 3
6

即结果是 6x 的最终值是 3.


还有一个区别。使用内部缩减,您可能根本得不到结果:

(define (my-if c t e)
  (if c t e))

(define (loop)
  (loop))

(my-if #t 42 (loop))

外减:

(my-if #t 42 (loop))
; definition of 'my-if'
(if #t 42 (loop))
; built-in 'if'
42

有内部缩减:

(my-if #t 42 (loop))
; definition of 'loop'
(my-if #t 42 (loop))
; definition of 'loop'
(my-if #t 42 (loop))
; definition of 'loop'
(my-if #t 42 (loop))
; definition of 'loop'
...

这永远不会终止。