2012-02-12 28 views
6

Vì tất cả các ví dụ trong hướng dẫn là với danh sách, tôi cảm thấy khó khăn để xem làm thế nào để sử dụng mô hình kết hợp trong vợt để viết phù hợp với điều kiện như OCaml không, ví dụ:mô hình có điều kiện phù hợp trong vợt

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 *) 
    ... 

Làm thế nào tôi sẽ viết một cái gì đó tương tự trong vợt?

Cảm ơn.

Trả lời

10

Thư viện racket/match bao gồm đối sánh mẫu có thể sử dụng các biến vị ngữ tùy ý thông qua mẫu ?. Cùng với and, bạn sẽ có thể nhận được Racket của matcher để cư xử. Mặc dù tôi là một chút yếu trong OCaml của tôi, tôi nghĩ rằng bản dịch sau đây của mã trên phù hợp với ý nghĩa của nó:

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

Các ? khớp có tiềm ẩn and nhúng trong nó, vì vậy các mã có thể được bày tỏ một chút hơn ngắn gọn như sau:

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

trong cả hai, các lambdas trong đó không được xem những gì đã xuất hiện, vì vậy tôi chỉ đặt tên cho chúng _ để biểu thị một đừng chăm sóc. Nhưng bạn có thể tưởng tượng ra các mô hình phức tạp hơn, nơi các vị từ có thể quan tâm sâu sắc về những gì chính xác đã khớp.

Eli đề nghị sử dụng tổng quát cond tại đây, vì không có bất kỳ kết hợp mẫu quan trọng nào trong mã. Tôi đồng ý. Mã sẽ trông giống như sau:

(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

Sử dụng quá nhiều '? 'Gợi ý rằng nó sẽ được thể hiện tốt hơn với một cụm từ' cond' đơn giản ... –

3

Kết hợp mẫu có thể dễ dàng được dịch thành chuỗi kiểm tra, không có ngôn ngữ mà bạn không thể làm điều đó.

Kết hợp mẫu OCaml (và có lẽ Haskell) là trình biên dịch dịch mã thành chuỗi kiểm tra tối ưu khi có thể (tức là chương trình sẽ không bao giờ kiểm tra hai lần cùng điều kiện, ít nhất là khi bạn tránh bảo vệ when).

+1

Tôi hy vọng rằng điều tương tự xảy ra trong Racket, vì nó có mô hình phù hợp rõ ràng, không? – GiantSquid

+1

Có thể là trường hợp nếu bạn sử dụng 'match', nhưng không phải nếu bạn sử dụng' cond'. Nhưng tôi không có chuyên gia về vợt, chỉ có ở OCaml. –

Các vấn đề liên quan