Как вы соответствуете с охранниками в ракетке?
В 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's match
форме? Я не мог найти это в документации
Для тех, кто не знаком со Scala, первый случай соответствует, если число равно или меньше 0, второй случай - это просто подстановочный знак, который соответствует всему остальному
другими словами, что бы я написал в ???
место для достижения функциональности, аналогичной описанной выше?
(define (times item number)
(match number
[??? '()]
[_ (cons item (times item (- number 1)))]))
2 ответа
Ракетка-х match
имеет дополнительный #:when
предложение, которое позволяет вам написать это почти так же, как вы это делали в Scala:
(define (times item number)
(match number
[n #:when (<= n 0) '()]
[_ (cons item (times item (- number 1)))]))
Я думаю, что это отвечает на ваш вопрос, в буквальном смысле. Но более идиоматической ракеткой было бы использовать 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
, как рекомендует руководство по стилю ракетки.
Оказывается, я не выглядел достаточно усердно, вот ответ:
(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)))]))