我正在尝试使用Racket函数,该函数将返回包含n个相同项目的列表。
我已经尝试过了:
#lang racket
(build-list 5 (lambda () '*))
但是我得到了错误:
build-list: contract violation
expected: (exact-nonnegative-integer? . -> . any/c)
given: #<procedure>
我想得到这个:(* * * * *)
。
我该怎么办?
答案 0 :(得分:3)
您传入的lambda函数需要接受一个参数,该参数是元素的索引(如错误消息(exact-nonnegative-integer? . -> . any/c)
所示)。当您尝试构建其元素根据索引位置而变化的列表时,此功能很有用。例如,(build-list 5 (lambda (n) n))
产生'(0 1 2 3 4)
在您的情况下,该参数没有用,因为您要构建的列表的所有元素都具有相同的内容。但是,无论如何,您都需要接受该参数。也就是说,使用(build-list 5 (lambda (n) '*))
。如果您觉得这很丑陋,那么还有thunk*
,它是创建可以接受任何内容但忽略参数的lambda的简写。因此,您也可以编写(build-list 5 (thunk* '*))
。如果您使用的是#lang racket/base
,则需要(require racket/function)
才能使用thunk*
。
答案 1 :(得分:2)
在这种情况下,我认为您应该使用const
-
#lang racket
(build-list 5 (const '*))
;; => '(* * * * *)
从文档中-
(const v) → procedure?
v : any
返回一个接受任何参数(包括关键字参数)并返回v
的过程。
示例-
((const 'foo) 1 2 3)
;; 'foo
((const 'foo))
;; 'foo
我看到您尝试实现自己的尾递归形式。这是一个不使用昂贵的append
操作的修订版本-
(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)
答案 2 :(得分:0)
测试,我发现了如何使用尾部递归来做到这一点:
#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 '())
> '(* * * * *)
我仅将此答案作为使用尾递归的示例。
答案 3 :(得分:0)
我认为您需要函数make-list
Modal