RacconMan
RacconMan

Reputation: 133

Racket: list-ref function

I was wondering if it was possible to write a list-ref function using the built-in functions foldl and foldr in racket. Basically, how can I change this piece of code using fold and foldr:

(define (my-list-ref lst n) (if (zero? n) (first lst) (list-ref (rest lst) (- n 1))))

Upvotes: 1

Views: 2846

Answers (1)

Óscar López
Óscar López

Reputation: 236004

Here's one possible way. The trick is to pass as an accumulator a list with two values: the first one is a flag telling you if you've found the element, and the second one keeps track of the current index, that we increment with each iteration. The flag is required because we need a way to say: stop looking for the index, we've already found it. Anyway foldl will have to consume the whole input list, because that's how it works.

(define (my-list-ref lst n)
  (let ((result
         (foldl (lambda (ele acc)
                  (cond ((first acc) acc)
                        ((= n (second acc)) (list #t ele))
                        (else (list #f (add1 (second acc))))))
                (list #f 0)
                lst)))
    (if (first result)
        (second result)
        (error "index out of bounds"))))

Some tests:

(my-list-ref '(a b c) 0)
=> 'a
(my-list-ref '(a b c) 1)
=> 'b
(my-list-ref '(a b c) 2)
=> 'c

(my-list-ref '() 0)
=> index out of bounds
(my-list-ref '(a b c) -1)
=> index out of bounds
(my-list-ref '(a b c) 3)
=> index out of bounds

Upvotes: 2

Related Questions