In one of my classes we are learning about functional programming, and I was told that this Racket code:
(define (my-if-bad x y z)
(if x y z))
(define (factorial-bad n)
(my-if-bad (= n 0) 1 (* n (factorial-bad (- n 1)))))
Will lead to infinite recursion. I understand this has to do with the fact that if
statements are lazily evaluated, but I'm not sure exactly what that means for this scenario. Any help would be appreciated
First we have to clarify a few things,
Going forward I assume you are running in #lang racket
To be a little bit more accurate in terms of terminology, if
statements are short-circuiting
. What that means is for an expression (if bxy)
the nested expression y
will NOT evaluate if b
is true
. Similarly x
will not evaluate if b
is false.
However, that is not what is going on here (replace my-if-bad
with regular if
and everything works. Actually quite the opposite. What is happening is function arguments in Racket are evaluated once, eagerly at function application .
So essentially in order to call my-bad-if
:
you first need to evaluate (factorial-bad (- n 1))
but
In order to evaluate (factorial-bad (- n 1))
you need to call my-bad-if
In order to call my-bad-if
you need to evaluate (factorial-bad (- n 1))
and so on.
So the terminating case never stops the evaluation.
The best way to understand this is the following code
(define y 5)
(define a (begin
(set! y (+ y 1))
y))
(define (add x) (+ x x))
There are two possibilities here, when calling add
with a
:
(+ (begin (set! y (+ y 1)) y) (begin (set! y (+ y 1)) y))
(let [x (begin (set! y (+ y 1)) y)]
(+ x x)
If it was the former, then
x
would set y= 5 + 1 = 6
x
evaluates y = 6 + 1 = 7
13
Which is NOT the case.
So in your case by the time the if
statement inside my-if-bad
is hit, the values are already evaluated and the if
's short circuiting ability is meaningless
If you use the stepper
in DrRacket
you can see how the evaluation unfolds, and the n
going -1, -2, -3...
Hope this helps
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.