Условное сопоставление с образцом в Racket - PullRequest
6 голосов
/ 13 февраля 2012

Поскольку все приведенные в руководстве примеры со списками, мне трудно понять, как использовать сопоставление с образцом в 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?

Спасибо.

Ответы [ 2 ]

10 голосов
/ 13 февраля 2012

Библиотека racket/match включает сопоставление с шаблоном, в котором могут использоваться произвольные предикаты в шаблоне ?.Наряду с and, вы должны быть в состоянии заставить матчера Ракета вести себя.Хотя я немного слаб в своем 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"]))

В обоих случаях лямбды не наблюдают за совпадениями, поэтому я просто назвал их _, чтобы обозначить неосторожность.Но вы можете представить себе более сложные шаблоны, в которых предикаты могли бы глубоко заботиться о том, что именно было сопоставлено.

Илай предлагает использовать здесь общий 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"]))
3 голосов
/ 14 февраля 2012

Сопоставление с образцом может быть легко переведено в последовательность тестов, нет языка, на котором вы не можете это сделать.

Что хорошо в сопоставлении с образцом в OCaml (и, возможно, в Haskell), так это то, что компилятор переводиткодируйте в оптимальную последовательность тестов, когда это возможно (т.е. программа никогда не будет тестировать дважды одно и то же условие, по крайней мере, когда вы избегаете when охранников).

...