Search code examples
schemeracketlet

How might I use letrec in this function so that it does the same job as it does with named let?


I've read here that named let can be rewritten with letrec. And so I proceeded to rewrite the following function with letrec:

(define (duplicate pos lst)
  (let dup ([i 0] [lst lst])
   (cond
     [(= i pos) (cons (car lst) lst)]
     [else (cons (car lst) (dup (+ i 1) (cdr lst)))])))

My attempt at this:

(define (duplicate pos lst)
  (letrec ((dup (lambda ([i 0] [lst lst])
     (cond
       [(= i pos) (cons (car lst) lst)]
       [else (cons (car lst) (dup (+ i 1) (cdr lst)))]))))))

Sadly, when I call it with (duplicate 1 (list "apple" "cheese burger!" "banana")) I get from Racket letrec: bad syntax (missing body). How might I rewrite duplicate with letrec?


Solution

  • As you can see in the documentation for letrec, it has these arguments:

    (letrec ([id val-expr] ...) body ...+)

    So, you have to add at least one body form after definitions.

    I also replaced cond with if (you have only two branches of code), (+ ... 1) with add1 and improved indentation:

    #lang racket
    
    (define (duplicate pos lst)
      (letrec ((dup (lambda ([i 0] [lst lst])
                      (if (= i pos)
                          (cons (car lst)
                                lst)
                          (cons (car lst)
                                (dup (add1 i) (cdr lst)))))))
        (dup)))
    

    Test:

    > (duplicate 1 (list "apple" "cheese burger!" "banana"))
    '("apple" "cheese burger!" "cheese burger!" "banana")