可以在 Racket Dispatch: 案例中使用 (range x y) 吗?

Can (range x y) be used in a Racket Dispatch: case?

我想在 case 语句中使用 (range x y) 而不是列出整个范围,这可能吗?

我相信第二个示例中的 (range 1 4) 正在返回一个列表,并且由于 2 != 列表,所以没有匹配项。

> (case 2
    [(1 2 3) "matched"]
    [else "no match"])
"matched"
> (case 2
    [(range 1 4) "matched"]
    [else "no match"])
"no match"

这是不可能的,因为 case uses implicit quote. In your example, it quotes all elements in list (range 1 4) and compares them (using equal?) 与 2.

(case 2
    [(range 1 4) "matched"]
    [else "no match"])
;2 is compared with 'range, 1, 4 => "no match"

(case 'range
    [(range 1 4) "matched"]
    [else "no match"])
;'range is compared with 'range, 1, 4 => "matched"

您可以在此处使用 cond

(let ((v 2))
  (cond ((member v (range 1 4)) "matched 1-4")
        ((member v (range 4 8)) "matched 4-8")
        (#true "no match")))

香草 case 将不起作用。 case 每个分支的 LHS 确实仅限于文字。

您可以使用其他形式,例如 condmatch。例如,

(match 2
  [-1 'foo]
  [0 'bar]
  [x #:when (member x (range 1 3)) 'baz]
  [x #:when (member x (range 3 5)) 'boo])

这是以效率不如使用 case 为代价的。

另一种方法是编写一个扩展为 case 的宏,例如:

#lang racket

(require syntax/parse/define
         (for-syntax racket/list))

(begin-for-syntax
  (define-syntax-class range-cls
    (pattern (#:range l:number r:number)
             #:with result (range (syntax-e #'l) (syntax-e #'r)))))

(define-simple-macro (case-range v [rgs:range-cls rhs ...] ...)
  (case v [rgs.result rhs ...] ...))

(case-range 2
  [(#:range -1 1) 'foo]
  [(#:range 1 3) 'bar]
  [(#:range 3 5) 'baz])