Roquentin
Roquentin

Reputation: 207

How to generate a list of lambdas in scheme?

I am trying to make a procedure which takes a list of lambdas, and uses the return value of these lambdas. In order to create and populate this list, I made the procedure:

(define generate-list-of-numbers-lambdas 
  (lambda (function) 
    (if (= (function) 3)
        (list (lambda () 2))
        (cons (lambda () (- (function) 1)) 
              (generate-list-of-numbers (lambda () (- (function) 1)))))))

This procedure takes a procedure as an argument, and generates a list of numbers from the return value of the argument procedure until 2 (IE the original argument is a procedure which returns 20, the generate-list-of-numbers makes a list (19 18 17... 3 2)

This procedure takes a procedure as an argument (the argument procedure has no arguments, itself, and just returns an integer), however, this generate-list-of-numbers-lambdas procedures generates a list, but only the first element is a lambda.

Upvotes: 0

Views: 317

Answers (1)

Mulan
Mulan

Reputation: 135415

Your procedure works just fine if you recur using generate-list-of-numbers-lambdas instead of generate-list-of-numbers; you simply forgot the -lambas part of the name.

A couple more things though. Your procedure calls (function) 3 times in the body. If the result needs to be used in more than one place, you should use a let binding.

(define generate-list-of-numbers
  (lambda (function)
    (let ((x (function))) ;; bind `x` to `(function)`
      (if (= x 3) ;; use x
          (list (lambda () 2))
          (cons (lambda () (- x 1)) ;; use x
                (generate-list-of-numbers (lambda () (- x 1)))))))) ;; use x

Next we see (lambda () ...) littered all about the code. A tiny dose of data abstraction goes a long way here -

(define num
  (lambda (x)
    (lambda () x)))

(define generate-list-of-numbers
  (lambda (function)
    (let ((x (function)))
      (if (= x 3)
          (list (num 2)) ;; use num
          (cons (num (- x 1)) ;; use num
                (generate-list-of-numbers (num (- x 1)))))))) ;; use num

;; calling our procedure is nicer too
(generate-list-of-numbers (num 20))

We see (num (- x 1)) twice again. It should be a let binding.

(define generate-list-of-numbers
  (lambda (function)
    (let ((x (function)))
      (if (= x 3)
          (list (num 2))
          (let ((next (num (- x 1)))) ;; bind `next`
            (cons next (generate-list-of-numbers next)))))) ;; use `next` twice

We used num to put numbers into our container. We will use val to take numbers out.

(define val
  (lambda (n)
    (n)))

(map val (generate-list-of-numbers (num 20)))
;; '(19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2)

Going back, we see we can use val in our procedure too. Lastly, we rename function to n. This allows us to think purely in terms of our numbers and forget that the values are wrapped a function (thunk), or some other data container.

(define generate-list-of-numbers
  (lambda (n) ;; `function` renamed to `n`
    (let ((x (val n))) ;; use `val` to read value of `n`
      (if (= x 3)
          (list (num 2))
          (let ((next (num (- x 1))))
            (cons next (generate-list-of-numbers next)))))))

(map val (generate-list-of-numbers (num 20)))
;; '(19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2)

All of that said, this is a weird procedure. I can only guess it is a homework assignment or something. It almost seems like you're trying to implement a lazy list of numbers, but it's not quite right. Starting the list at n - 1 and ending at 2 is another obscure choice and red flag. If you can provide a broader goal, I may be able to update the answer and provide additional help.

Upvotes: 1

Related Questions