Dr Racket 列表函数
Dr Racket list function
Define a procedure likenate
that takes a list and returns the list with the symbol 'like
inserted between each pair of adjacent elements in the given list.
我觉得这应该很容易,但我一直在获取列表列表,因此检查预期不起作用。我在这个问题上被困了一个多小时。我试过 append 和 list* 以及其他一些东西,但我无法弄清楚如何将一个列表的列表折叠成一个列表,或者只是让函数与检查期望一起工作。 BSL+ 对此的任何帮助都会非常有用。无论如何,这就是我所拥有的:
; likenate : List -> List
(check-expect (likenate (list 'here 'be 'dragons))
(list 'here 'like 'be 'like 'dragons))
(check-expect (likenate (list 'that 'is 'so 'cool))
(list 'that 'like 'is 'like 'so 'like 'cool))
(check-expect (likenate (list 'like 'like))
(list 'like 'like 'like))
(define (likenate list_like)
(cond [(empty? list_like) '()]
[else (list (first list_like) 'like (likenate (rest list_like)))
]))
这是我的版本:
(define (likenate lst)
(cond ((empty? (rest lst)) lst)
(else (list* (first lst) 'like (likenate (rest lst))))))
你非常接近,而且你在考虑 list*
的方向上是正确的。事实上,在您的尝试中将 list
替换为 list*
会产生这个程序,它几乎完全正确:
(define (likenate lst)
(cond [(empty? lst) '()]
[else (list* (first lst) 'like (likenate (rest lst)))]))
您可以将 list*
视为多个 cons
的 shorthand。简单来说,(list* a b c)
等价于(cons a (cons b c))
。这是必要的,因为 likenate
的结果是 list,因此它需要是通过将两个新元素添加到这个列表。
该实现 几乎 有效,但有一个小问题。它会在列表的末尾插入 'like
元素,所以你最终会得到这样的列表,而不是:
(list 'here 'like 'be 'like 'dragons 'like)
只需在 cond
中添加一个额外的子句来专门处理最后一个元素,一切都应该正常工作:
(define (likenate lst)
(cond [(empty? lst) '()]
[(empty? (rest lst)) lst]
[else (list* (first lst) 'like (likenate (rest lst)))]))
这是另一个使用宏的解决方案 define-syntax
:
(define-syntax likenate
(syntax-rules ()
[(_ ()) '()]
[(_ (e1 e2 ...)) (cons e1 (cons 'like (likenate (e2 ...))))]))
一个区别是调用这个函数时,不需要调用list
函数:
(likenate ('here 'be 'dragons))
=> (here like be like dragons like)
Define a procedure
likenate
that takes a list and returns the list with the symbol'like
inserted between each pair of adjacent elements in the given list.
我觉得这应该很容易,但我一直在获取列表列表,因此检查预期不起作用。我在这个问题上被困了一个多小时。我试过 append 和 list* 以及其他一些东西,但我无法弄清楚如何将一个列表的列表折叠成一个列表,或者只是让函数与检查期望一起工作。 BSL+ 对此的任何帮助都会非常有用。无论如何,这就是我所拥有的:
; likenate : List -> List
(check-expect (likenate (list 'here 'be 'dragons))
(list 'here 'like 'be 'like 'dragons))
(check-expect (likenate (list 'that 'is 'so 'cool))
(list 'that 'like 'is 'like 'so 'like 'cool))
(check-expect (likenate (list 'like 'like))
(list 'like 'like 'like))
(define (likenate list_like)
(cond [(empty? list_like) '()]
[else (list (first list_like) 'like (likenate (rest list_like)))
]))
这是我的版本:
(define (likenate lst)
(cond ((empty? (rest lst)) lst)
(else (list* (first lst) 'like (likenate (rest lst))))))
你非常接近,而且你在考虑 list*
的方向上是正确的。事实上,在您的尝试中将 list
替换为 list*
会产生这个程序,它几乎完全正确:
(define (likenate lst)
(cond [(empty? lst) '()]
[else (list* (first lst) 'like (likenate (rest lst)))]))
您可以将 list*
视为多个 cons
的 shorthand。简单来说,(list* a b c)
等价于(cons a (cons b c))
。这是必要的,因为 likenate
的结果是 list,因此它需要是通过将两个新元素添加到这个列表。
该实现 几乎 有效,但有一个小问题。它会在列表的末尾插入 'like
元素,所以你最终会得到这样的列表,而不是:
(list 'here 'like 'be 'like 'dragons 'like)
只需在 cond
中添加一个额外的子句来专门处理最后一个元素,一切都应该正常工作:
(define (likenate lst)
(cond [(empty? lst) '()]
[(empty? (rest lst)) lst]
[else (list* (first lst) 'like (likenate (rest lst)))]))
这是另一个使用宏的解决方案 define-syntax
:
(define-syntax likenate
(syntax-rules ()
[(_ ()) '()]
[(_ (e1 e2 ...)) (cons e1 (cons 'like (likenate (e2 ...))))]))
一个区别是调用这个函数时,不需要调用list
函数:
(likenate ('here 'be 'dragons))
=> (here like be like dragons like)