Racket中的条件模式匹配

Ser*_*lla 6 ocaml functional-programming pattern-matching racket

由于指南中的所有示例都带有列表,我发现很难看到如何在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 *)
    ...
Run Code Online (Sandbox Code Playgroud)

我如何在Racket中写出类似的东西?

谢谢.

dyo*_*yoo 10

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")
Run Code Online (Sandbox Code Playgroud)

?匹配器有一个隐式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"]))
Run Code Online (Sandbox Code Playgroud)

在这两个中,那里的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"]))
Run Code Online (Sandbox Code Playgroud)

  • 使用这么多`?`表示用一个普通的`cond`表达得更好...... (3认同)