So as far as I understand, the following: let, let*, letrec and letrec* are synthetics sugars used in Scheme/Racket.
Now, if I have a simple program:
(let ((x 1)
(y 2))
(+ x y))
It is translated into:
((lambda (x y) (+ x y)) 1 2)
If I have:
(let* ((x 1)
(y 2))
(+ x y))
It is translated into:
((lambda (x) ((lambda (y) (+ x y))) 2) 1)
Now, for my first question, I understand the meaning of a letrec expression, which enables one to use recursion inside a let, but I do not understand how exactly it is done. What is letrec translated to?
For example, what will
(letrec ((x 1)
(y 2))
(+ x y))
be translated into?
The second question is similar about letrec* - But for letrec* I do not understand how exactly it differs from letrec? And also, what will a letrec* expression be translated into?
See the paper "Fixing Letrec: A Faithful Yet Efficient Implementation of Scheme’s Recursive Binding Construct" by Oscar Waddell, Dipanwita Sarkar, and, R. Kent Dybvig.
The paper starts with a simple version and proceeds to explain a more sophisticated expansion:
https://www.cs.indiana.edu/~dyb/pubs/fixing-letrec.pdf