1
(define length-it
  (lambda (ls)
    (length ls 0)))

(define length
  (lambda (ls acc)
    (if (null? ls)
        acc
        (length (cdr ls) (+ acc 1)))))

How to use letrec to put the function length within the body of function length-it?

The output should be (length-it '(1 2 3)) -> 3.

Will Ness
  • 70,110
  • 9
  • 98
  • 181

1 Answers1

2

Let's start with what we've got:

(define length-it 
   (lambda (ls) 
      (length ls 0)))

But actually, since there's also a built-in function called length too, let's rename ours to my-length:

(define my-length
  (lambda (ls acc)
    (if (null? ls)
        acc
        (my-length (cdr ls) (+ acc 1)))))

and now,

(define length-it 
   (lambda (ls) 
      (my-length ls 0)))
=
(define length-it 
   (let ((init 0))
     (lambda (ls) 
        (my-length ls 0))))       ;; (0)
=
(define length-it 
   (let ((init 0))                ;; (1)
     (lambda (ls) 
        (my-length ls init))))    ;; (2)

Does this work? To what entity does init(2) refer? Is it init(1)?

Next,

=
(define length-it 
   (let ((init 0)                                      ;; (0)
         (my-length                                    ;; (1)
            (lambda (ls acc) 
               (if (null? ls) 
                   acc 
                   (my-length (cdr ls) (+ acc 1))))))  ;; (2)
     (lambda (ls) 
        (my-length ls init))))                         ;; (3)

Now does this work? (be sure to test this in a new, fresh environment, without my-length being defined separately there at all).

No? Why not?

To what entity does the name init(3) refer? To what does my-length(3) refer? To what does the name my-length(2) refer? Would it work if my-length(2) were referring to my-length(1) as does my-length(3)? Since it doesn't work, my-length(2) must refer to some other my-length defined above the let but do we have any more of them anywhere there?

So can you make it work? Were you supposed to use let there, or that other primitive, letrec? Are the two exactly the same? Probably not, otherwise why would they name the same thing twice? So can we try using the other one there? Would it perhaps make my-length(2) indeed refer to my-length(1) as it was supposed to do?

Does it work now?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • and you say...? -- comments? feedback? anything? – Will Ness Feb 17 '21 at 14:27
  • If OP applies elbow grease and works through this, they might learn something. But, they may get confused when trying the final definition of `length-it` above; the inner `length` will be confused with the built-in `length` when errors are issued by the compiler. It might aid the clarity of error messages to change `length` to `my-length`. – ad absurdum Feb 17 '21 at 15:11
  • @Will Ness: thank you so much for your detailed explanation. It works. – user15225644 Feb 17 '21 at 18:04
  • 2
    @user15225644 -- please consider [accepting answers](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) that you find useful. This signals to future visitors the the answer worked, rewards the answerer for taking the time to help (especially nice for a detailed answer such as this one), and gives you a small rep bump, too. – ad absurdum Feb 18 '21 at 01:12