Racket 中的条件模式匹配

发布于 2025-01-04 16:41:03 字数 327 浏览 3 评论 0原文

由于指南中的所有示例都带有列表,因此我发现很难了解如何在 Racket 中使用模式匹配来编写像 OCaml 那样的条件匹配,例如:

read ~var_a var_b s = match s.[0] with
    | _ when var_b >= var_a + 4 ->
        (* Do something *)
    | "a" when is_negative var_b -> 
        (* Do something else *)
    ...

我如何在 Racket 中编写类似的内容?

谢谢。

Since all the examples in the guide are with lists, I find it difficult to see how to use pattern matching in Racket to write conditional matching like OCaml does, for example:

read ~var_a var_b s = match s.[0] with
    | _ when var_b >= var_a + 4 ->
        (* Do something *)
    | "a" when is_negative var_b -> 
        (* Do something else *)
    ...

How would I write something similar in Racket?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

末骤雨初歇 2025-01-11 16:41:03

racket/match 库包含可以通过以下方式使用任意谓词的模式匹配: ? 模式。与 一起,您应该能够让 Racket 的匹配器正常工作。虽然我的 OCaml 能力有点弱,但我认为上面代码的以下翻译与其含义相符:

(define (my-read #:var-a var-a var-b s)
  (match (string-ref s 0)
    [(and _
          (? (lambda (_)
               (>= var-b (+ var-a 4)))))
     "do something"]
    [(and '#\a
          (? (lambda (_)
               (< var-b 0))))
     "do something else"]))

;; Exercising the first case:     
(my-read #:var-a 50
         60 "blah")

;; Exercising the second case:
(my-read #:var-a 50
         -40 "alphabet")

? 匹配器内嵌了隐式 and ,因此代码可以更简洁地表达为:

(define (my-read #:var-a var-a var-b s) 
  (match (string-ref s 0)
    [(? (lambda (_)
          (>= var-b (+ var-a 4))))
     "do something"]
    [(? (lambda (_)
          (< var-b 0))
        #\a)
     "do something else"]))

在这两种情况下,其中的 lambda 不观察匹配的内容,因此我只是将它们命名为 _ 来表示不关心。但是您可以想象更复杂的模式,其中谓词可以深入关心确切匹配的内容。

Eli 建议在这里使用通用的 cond,因为代码中没有任何重要的模式匹配。我同意。代码如下所示:

(define (my-read #:var-a var-a var-b s) 
  (cond
    [(>= var-b (+ var-a 4))
     "do something"]
    [(and (char=? (string-ref s 0) #\a)
          (< var-b 0))
     "do something else"]))

The racket/match library includes pattern matching that can use arbitrary predicates through the ? pattern. Along with and, you should be able to get Racket's matcher to behave. Although I'm a little weak in my OCaml, I think the following translation of the code above matches its meaning:

(define (my-read #:var-a var-a var-b s)
  (match (string-ref s 0)
    [(and _
          (? (lambda (_)
               (>= var-b (+ var-a 4)))))
     "do something"]
    [(and '#\a
          (? (lambda (_)
               (< var-b 0))))
     "do something else"]))

;; Exercising the first case:     
(my-read #:var-a 50
         60 "blah")

;; Exercising the second case:
(my-read #:var-a 50
         -40 "alphabet")

The ? matcher has an implicit and embedded within it, so the code can be expressed slightly more succinctly as:

(define (my-read #:var-a var-a var-b s) 
  (match (string-ref s 0)
    [(? (lambda (_)
          (>= var-b (+ var-a 4))))
     "do something"]
    [(? (lambda (_)
          (< var-b 0))
        #\a)
     "do something else"]))

In both, the lambdas in there aren't watching what got matched, so I just named them _ to denote a don't-care. But you can imagine more sophisticated patterns where the predicates could care deeply about what exactly got matched.

Eli suggests using a general cond here, since there isn't any significant pattern matching in the code. I agree. The code would look like this:

(define (my-read #:var-a var-a var-b s) 
  (cond
    [(>= var-b (+ var-a 4))
     "do something"]
    [(and (char=? (string-ref s 0) #\a)
          (< var-b 0))
     "do something else"]))
冷夜 2025-01-11 16:41:03

模式匹配可以很容易地转化为一系列测试,没有一种语言不能做到这一点。

OCaml(可能还有 Haskell)模式匹配的优点在于,编译器在可能的情况下将代码转换为最佳测试序列(即程序永远不会测试两次相同的条件,至少当您避免 守卫时)。

Pattern-matching can easily be translated into a sequence of tests, there is no language where you cannot do that.

What's great with OCaml (and probably Haskell) pattern-matching is that the compiler translates the code into the optimal sequence of tests when it is possible (i.e. the program will never test twice the same condition, at least when you avoid the when guards).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文