在Scala中,您可以执行以下操作:
def times[A](item: A, number: Int): List[A] = number match {
case n if n <= 0 => Nil // Nil = '()
case _ =>
// equivalent to [_ (cons item (times item (- number 1)))]
item :: times(item, number - 1)
}
有可能使用Racket的match
形式来做这样的事情吗?我在文档中找不到它
对于那些不熟悉Scala的人来说,如果数字等于或小于0,则第一种情况匹配,第二种情况只是一个通配符,它匹配其他所有
换言之,我将在???
点中写些什么来实现与上述类似的功能?
(define (times item number)
(match number
[??? '()]
[_ (cons item (times item (- number 1)))]))
Racket的match
有一个可选的#:when
子句,它可以让你像在Scala:中一样编写它
(define (times item number)
(match number
[n #:when (<= n 0) '()]
[_ (cons item (times item (- number 1)))]))
我认为这确实回答了你的问题。但更惯用的Racket是使用cond
进行类似的测试——这是一个简单的条件测试,不需要任何破坏:
(define (times item number)
(cond [(<= number 0) '()]
[else (cons item (times item (- number 1)))]))
尽管我可能会改变主意:
(define (times item number)
(cond [(positive? number) (cons item (times item (- number 1)))]
[else '()]))
当然,对于如此简单的事情,你可以使用if
:
(define (times item number)
(if (positive? number)
(cons item (times item (- number 1)))
'()))
然而,我越来越喜欢使用cond
,正如Racket风格指南所建议的那样。
原来我看得不够仔细,答案是:
(define (times item number)
(match number
[(? (lambda (n) (<= n 0))) '()]
[_ (cons item (times item (- number 1)))]))
(? expr patt)
定义了一个保护。
以上内容可以更简洁地写成:
(define (lteq-0? n) (<= n 0))
(define (times item number)
(match number
[(? lteq-0?) '()]
[_ (cons item (times item (- number 1)))]))