【问题标题】:Conditional pattern matching in RacketRacket 中的条件模式匹配
【发布时间】:2012-02-12 21:55:55
【问题描述】:

由于指南中的所有示例都带有列表,我发现很难看到如何在 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 中编写类似的东西?

谢谢。

【问题讨论】:

    标签: functional-programming pattern-matching ocaml racket


    【解决方案1】:

    racket/match 库包含可以通过? 模式使用任意谓词的模式匹配。与and 一起,您应该能够让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"]))
    

    在这两种情况下,其中的 lambdas 都没有看到匹配的内容,所以我只是将它们命名为 _ 以表示不关心。但是您可以想象更复杂的模式,其中谓词可以非常关心精确匹配的内容。

    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"]))
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 我希望在 Racket 中也会发生同样的情况,因为它具有明确的模式匹配功能,不是吗?
      • 如果您使用match,可能是这种情况,但如果您使用cond,则不是。但我不是 Racket 方面的专家,只在 OCaml 方面。
      猜你喜欢
      • 2020-01-17
      • 2015-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 2019-07-18
      • 2017-03-09
      相关资源
      最近更新 更多