For example, where letrec / letrec * is better than let with internal defines or named let?

Kent Dybwig gives two examples in the circuit programming language for letrec and letrec *:

(letrec ([sum (lambda (x)
             (if (zero? x)
                 0
                 (+ x (sum (- x 1)))))])
   (sum 5))

and

(letrec* ([sum (lambda (x)
            (if (zero? x)
                    0
                (+ x (sum (- x 1)))))]
         [f (lambda () (cons n n-sum))]
         [n 15]
         [n-sum (sum n)])
  (f))

The first can also be written as named let:

(let sum ([x 5]) 
  ((lambda (x)
                 (if (zero? x)
                     0
                     (+ x (sum (- x 1))))) x))  

and the second can be written as let with internal defines:

(let ()
  (define sum  (lambda (x)
               (if (zero? x)
               0 
                   (+ x (sum (- x 1))))))
  (define f (lambda () (cons n n-sum)))
  (define n 15)
  (define n-sum (sum n))
  (f))

The letrec / letrec * forms do not seem more concise or clear than named let or let forms with internal defining forms.

Can someone show me an example where letrec / letrec * improves the code or is necessary instead of the name let or let with internal defines.

+5
source share
3 answers

Yes, the first example can be rewritten using the name let, but note that there is no form lambda:

(let sum ([x 5])
  (if (zero? x)
    0
    (+ x (sum (- x 1)))))

- , " " ( - ) . , , , , , , , .

-, , let - , , letrec. - letrec, named- let s. ( : .)

, , , named- let s: , letrec ( letrec, letrec* R5RS letrec* R6RS). , , , letrec. , , letrec, , sum - undefined. letrec*, R6RS: , , , , . letrec* . (, , , , ).

( , (a) Racket, Chez , , , .)

+6

; let define letrec.

, . , Scheme. 981 , 206 878 ( , , ). , 8 16 8 .

, letrec ? 16. 7000 let let* ( , , ). , letrec .

, , letrec.

+2

: letrec let . letrec let, set! . , :

(let
  ([sum (void)])
  (set! sum (lambda (x) (if (zero? x) 0 (+ x (sum (- x 1))))))
  (sum 5))

, ( , let let* - , ):

(let
  ([sum (void)] 
  (set! sum (lambda (x) (if (zero? x) 0 (+ x (sum (- x 1))))))
  (let
    [f (void)] 
    (set! f (lambda () (cons n n-sum)))
    (let 
      [n (void)]
      (set! n 15)
      (let
        [n-sum (void)])
        (set! n-sum (sum n))
        (f))

600%, let, , letrec ( ). , let let letrec let. , .

, letrec, . , let , define set! ( ).

, , , , , , , , ( letrec, let , YMMV). , , ( ).

, , :

(letrec
 ([even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))]
  [odd? (lambda (n) (if (zero? n) #f (even? (- n 1))))])
  (even? 88))   

define :

(let ()
  (define even? (lambda (n) (if (zero? n) #t (odd? (- n 1)))))
  (define odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))
  (even? 88))

So the code letrecis actually shorter. And honestly, if you are doing something like the latter, why not settle for begin?

(begin
  (define even? (lambda (n) (if (zero? n) #t (odd? (- n 1)))))
  (define odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))
  (even? 88))

I suspect that it is beginmore built-in and, as such, will not receive macro expansion (for example, it letwill). Finally, a similar problem was raised in overflowing the Lisp stack a bit backward with more or less the same point.

+1
source

All Articles