Here's what's happening:
When you (define fact x!), you aren't permanently linking fact to x!. You're making fact equal to whatever x! is at the time of fact's definition.
So (define fact x!) is actually equivalent to:
(define fact
(lambda(x)
(if (= x 1) 1 (* x (x! (- x 1))))))
Next, you redefine x!:
(define x! (lambda (x) x))
But that does not change fact - it only changes x!. Next, you do this:
(fact 5)
Here's what the interpreter 'does' next (it may actually do it slightly differently - but only trivially so, and this should at least help you understand the behaviour of your program):
Replacing fact with its definition gives:
(lambda(x)
(if (= x 1) 1 (* x (x! (- x 1)))))
Replacing x! with its new definition gives:
((lambda(x)
(if (= x 1)
1
(* x
(- ((lambda (x)
x)
x)
1))))
5)
...Simplifying gives:
((lambda(x)
(if (= x 1)
1
(* x (- x 1))))
5)
...
(if (= 5 1)
1
(* 5 (- 5 1)))
...
(if #f
1
(* 5 (- 5 1)))
...Resolving the conditional and simplifying the substraction gives:
(* 5 4)
...Which yields 20.