Build a list with the same n items

Viewed 277

I'm trying to do with Racket a function that will return a list with n identical items.

I have tried this:

#lang racket

(build-list 5 (lambda () '*))

But I get the error:

build-list: contract violation
  expected: (exact-nonnegative-integer? . -> . any/c)
  given: #<procedure>

I want to get this: (* * * * *).

How can I do it?

4 Answers

The lambda function that you pass in needs to accept one argument which is the index of the element (as you can see from the error message: (exact-nonnegative-integer? . -> . any/c)). This is useful when you are trying to build a list whose elements vary depending on index position. E.g., (build-list 5 (lambda (n) n)) produces '(0 1 2 3 4)

In your case, the argument is useless as the list that you want to build has the same content for all elements. However, you need to accept the argument anyway. That is, use (build-list 5 (lambda (n) '*)). If you find this ugly, there's also thunk* which is a shorthand for creating a lambda that accepts anything but ignores arguments. So you can also write (build-list 5 (thunk* '*)). If you are using #lang racket/base, you need to (require racket/function) to use thunk*.

I think you should use const in this case -

#lang racket
(build-list 5 (const '*))
;; => '(* * * * *)

From the docs -

(const v) → procedure?
v : any

Returns a procedure that accepts any arguments (including keyword arguments) and returns v.

Examples -

((const 'foo) 1 2 3)
;; 'foo

((const 'foo))
;; 'foo

I see you tried implementing your own tail-recursive form. Here's a revision that doesn't use the costly append operation -

(define (my-build-list n proc)
  (let loop ((acc empty)
             (n (sub1 n)))
    (if (< n 0)
        acc
        (loop (cons (proc n) acc)
              (sub1 n)))))

(my-build-list 5 (const '*))
;; '(* * * * *)

(my-build-list 5 identity)
;; '(0 1 2 3 4)

Testing, I have found how to do it using tail recursion:

#lang racket

(define my-build-list
  (lambda (n l)
    (if (zero? n) l (my-build-list (- n 1) (append l (list '*))))))

(my-build-list 5 '())

> '(* * * * *)

I only add this answer as an example of how to do it using tail recursion.

I think you want the function make-list

(make-list 5 '*) => (* * * * *)
Related