racket

Racket built-in repetition functions


I was looking for a way to repeat a function call a certain number of times and accumulate the results in a list and couldn't find anything in the standard library, so I wrote one. It's simple to write, but it seems like such an obvious thing that I feel like there must be an accepted way of doing this using standard library functions.

Here are the two functions I'm looking to replace:

(define (repeat n f)
  (unless (<= n 0)
    (f)
    (repeat (sub1 n) f)))

(define (accumulate n f)
  (let loop ([n n] [l empty])
    (if (<= n 0)
        l
        (loop (sub1 n)
              (cons (f) l)))))

Is there any simpler way of achieving this?


Solution

  • If your function does not any take arguments, you can use build-list

    Example:

    #lang racket
    
    ;; The function you want to call many times
    (define (f)
      #t)
    
    ;; Use build list with a lambda to wrap your function because
    ;; build-list want a function takin integer as its second argument
    (build-list 5 (lambda (x) (f)))
    

    result:

    '(#t #t #t #t #t)
    

    Edit: you can also define a function to wrap the lambda

    (define (repeat-then-accumulate n f)
      (build-list n (lambda (x) (f)))
      )
    

    Usage:

    ;; Using the f function defined earlier
    (repeat-then-accumulate 10 f)
    

    result:

    '(#t #t #t #t #t #t #t #t #t #t) 
    

    Edit2: If you want to have fixed args, you could do something like

    #lang racket
    
    ;; The function you want to call many times
    (define (f a b)
      (+ a b))
    
    
    (define (repeat-then-accumulate n f args)
      (build-list n (lambda (x) (apply f args)))
      )
    

    Usage:

    (repeat-then-accumulate 10 f '(3 5))
    

    Result:

    '(8 8 8 8 8 8 8 8 8 8)