Question

I've been confused for the past two days about completing this kind of problem.

The function that is produced (by makeMixer) takes as input an integer N, and outputs the Nth item in the original list. For example, if makeListPickerFor were called as follows:

    (makeListPickerFor '(4 0 -2 -3 5))

a function would be produced that takes as input an integer, for example 3, and returns that item in the list (for 3, it would output -2, because -2 is the 3rd item in the original list).

Thus, if the original call had been made as follows:

   (define S (makeListPickerFor '(4 0 -2 -3 5)))

then the the produced function S would behave as follows:

   (S 4)   *** would return -3, because -3 is the 4th item in the original list
   (S 2)   *** would return 0, because 0 is the 2nd item in the original list

Any help in the right direction will greatly help.

Was it helpful?

Solution 2

Try

(define (makeListPickerFor l)
  (lambda (n)
    (list-ref l n)))

so makeListPickerFor returns a function that still has access to the initial list l through a closure. Then

> (define S (makeListPickerFor '(4 0 -2 -3 5)))
> (S 4)
5
> (S 2)
-2

Note that in Scheme lists are 0-indexed hence the results. If you want to use 1-indexed, change to

(define (makeListPickerFor l)
  (lambda (n)
    (list-ref l (- n 1))))

> (define S (makeListPickerFor '(4 0 -2 -3 5)))
> (S 4)
-3
> (S 2)
0

The procedure could also be expressed as

(define makeListPickerFor
  (lambda (l)
    (lambda (n)
      (list-ref l (- n 1)))))

this is exactly the same as the previous procedure, since (define (f x)) is syntactic sugar for (define f (lambda (x))), but makes it clearer that it is a procedure returning a procedure.

OTHER TIPS

This phenomena is called a closure. The closure is basically the internal state returned by makeListPickerFor in form of a function. Assigning that to some name S results in S being a function that you can make subsequent calls to. This function then has access to that internal state within the scope of the first function that returned it.

Here is an alternative way to define it:

(define (make-picker lst)
  (define (picker n)
    (list-ref lst (- n 1)))
  picker)

(define list-len 10000000)
(define f (make-picker (range list-len 0 -1)) ; range is #!racket specific
(f 1)        ; ==> 10000000
(f list-len) ; ==> 1

And here is a more efficient one for very large lists in #!racket:

(define (make-picker-hash lst)
  (define hash 
    (make-immutable-hasheqv (map cons 
                                 (range 1 (add1 (length lst))) 
                                 lst)))
  (lambda (x)
    (hash-ref hash x))) 

(define fh (make-picker-hash (range list-len 0 -1)))
(fh list-len) ; ==> 1
(fh 1)        ; ==> 10000000 (list-len)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top