It's best to read the official descriptions of R5RS let, let * and letrec.
Shortly speaking:
(let ((x 2)) (let ((x 3) (yx)) y) => 2 (let ((x 2)) (let* ((x 3) (yx)) y) => 3
Thus, the difference between let and let * will evaluate all the bindings relative to the level above (therefore, it does not matter in which order they are listed), and let * do it sequentially. (let * ((xa) (by))) be equivalent (let ((xa)) (let ((by))).
Letrec, on the other hand, allows you to bind recursive values. This way you can write a recursive function that you only need within the scope and bind it to a name using letrec.
Greg source share