VansFannel
VansFannel

Reputation: 45921

Build a list with the same n items

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?

Upvotes: 2

Views: 656

Answers (4)

gmw
gmw

Reputation: 131

I think you want the function make-list

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

Upvotes: 0

Mulan
Mulan

Reputation: 135227

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)

Upvotes: 2

VansFannel
VansFannel

Reputation: 45921

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.

Upvotes: 0

Sorawee Porncharoenwase
Sorawee Porncharoenwase

Reputation: 6502

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*.

Upvotes: 3

Related Questions