jeebface
jeebface

Reputation: 841

Why doesn't this Racket code terminate?

I'm reading about lazy evaluation and having trouble understanding a basic example they gave.

#lang racket
(define (bad-if x y z)
  (if x y z))
(define (factorial-wrong x)
  (bad-if (= x 0)
          1
          (* x (factorial-wrong (- x 1)))))

(factorial-wrong 4)

I'm a little confused as to why this program never terminates. I know the following code works just fine:

(define (factorial x)
  (if (= x 0)
      1
      (* x (factorial (- x 1)))))

(factorial 4)

So I'm assuming it has something to do with scope. I tried step by step debugging and factorial-wrong executes the recursion function even when x is mapped to 0.

Upvotes: 3

Views: 228

Answers (2)

John Clements
John Clements

Reputation: 17203

Use the stepper!

To be more specific:

  • Snip the #lang racket off the top of your program
  • Change the language level to "Intermediate Student"
  • Click on the Step button. Watch carefully to see where things go off the rails.

Upvotes: 4

uselpa
uselpa

Reputation: 18917

The standard if

(if test-expr then-expr else-expr)

will only evaluate either then-expr or else-expr, depending on test-expr, because this if is either a special form or a syntactic extension based on a special form, which means it doesn't follow the normal evaluation rules.

bad-if, on the other hand, is a standard procedure. In that case, Scheme first evaluates both expressions since they are parameters to the procedure bad-if before actually executing bad-if. So, even for x = 0, (* x (factorial -1)) will be evaluated, which will in turn evaluate (* x (factorial -2)) and so on, in an endless loop.

Upvotes: 5

Related Questions