Search code examples
schemeletrec

confusion of letrec, Scheme


I am struggling the difference between let, letrec, let* ... since scheme is not my primary programming language, my memory is not existing for long time.. I have this function.. now I am very confusing with letrec here.. this is again recursion.that I can understand...but can't make connection enough in this code.. (maybe still confuse about recursion) can someone explain why here need letrec

(define myFunc
  (lambda (start end res func)
    (letrec ((func:rec_func
              (lambda (x i y)
                (if (>= i start)
                    (func:rec_func (cons i x) (- i res) (cons (func i) y))  ;; line6
                    (cons x (cons y '()))))))                               ;; line7
      (func:rec_func '() end '()))))

(edited) what I understand it's tail recursion

-> [Q1] Does it tail recursion?

-> [Q2] then, should use always letrec for tail recursion?

this function returns the lists of x, y with boundaries of start, end so it checks index i is inside boundaries , if yes, then do line 6

-> [Q3]then, what does line6 ? I can't get the line6


Solution

  • [Q1] Does it tail recursion?

    Answer Yes, it does tail recursion.

    [Q2] then, should use always letrec for tail recursion?

    Answer There are two ways of interpreting your question.

    1. Should we always use letrec for tail recursion? I don't think you meant to ask this. But ...

      The answer is no. Top level lambda functions can also be used for tail recursion.

    2. Should letrec always use tail recursion?

      The answer to that is: It's better for any recursive function to be tail recursive. If you can, you should make it tail recursive.

    [Q3] then what does line6 ?

    The code at line 6 performs the recursive call.

    Let's say start is 0, end is 5, and res is 1. In the first call to func:rec_func, x is the empty list (), i is 5, and y is the empty list ().

    When the first recursive function is called at line 6, the arguments are (cons i x), (- i res), and (cons (func i) y), which evaluate to: (5), 4, and ((func 5).

    In the next iteration, the arguments are (4 5), 3, and ((func 4) (func 5)).

    It continues until i becomes less than start. Then the recursion stops with the result ((0 1 2 3 4 5) ((func 0) (func 1) (func 2) (func 3) (func 4) (func 5)))

    The code at line 7 is executed when the terminating criterion for the recursion is met, which is when (>= i start) is false.