2010-05-17 27 views
11

Trong "Lập trình F #" Tôi đã xem qua một mô hình khớp như thế này (tôi đơn giản hóa một chút):Hiểu mô hình kết hợp với nhà điều hành nhược điểm

let rec len list = 
    match list with 
    | [] -> 0 
    | [_] -> 1 
    | head :: tail -> 1 + len tail;; 

Thực tế, tôi hiểu rằng trận đấu cuối cùng nhận người đứng đầu và đuôi của danh sách. Về mặt khái niệm, tôi không hiểu tại sao nó hoạt động. Theo như tôi hiểu, :: là toán tử cons, nối thêm một giá trị ở vị trí đầu của một danh sách, nhưng nó không giống như tôi đang được sử dụng như một toán tử ở đây. Tôi có nên hiểu điều này dưới dạng "cú pháp đặc biệt" cho các danh sách, trong đó :: được hiểu là toán tử hay "mẫu đối sánh" tùy thuộc vào ngữ cảnh? Hoặc ý tưởng tương tự có thể được mở rộng cho các loại khác ngoài danh sách, với các toán tử khác không?

Trả lời

10

Ngoài câu trả lời của Brian, có một số điểm đáng chú ý. Cú pháp h::t thể được sử dụng cả hai như là một nhà điều hành như một mô hình:

let l = 1::2::[]     // As an operator 
match l with x::xs -> 1 | [] -> 0 // As a pattern 

Điều này có nghĩa rằng nó là một chút đặc biệt xây dựng, bởi vì các nhà khai thác khác (ví dụ +) không thể được sử dụng như hình mẫu (ví phân hủy kết quả trở lại đối số của toán tử) - rõ ràng, đối với +, điều này sẽ không rõ ràng.

Ngoài ra, mẫu [_] là điều thú vị vì đó là ví dụ về mẫu lồng nhau. Nó soạn:

  • _ - Gạch dưới mô hình, mà phù hợp với bất kỳ giá trị và không ràng buộc bất kỳ biểu tượng
  • [ <pattern> ] - Single-yếu tố danh sách mẫu, mà phù hợp với một danh sách với các yếu tố duy nhất và phù hợp với các yếu tố của danh sách với lồng nhau <pattern>.

Bạn cũng có thể viết match 1::[] with | [x] -> x để trả về giá trị của phần tử đơn lẻ (trong trường hợp này là 1).

+0

Cảm ơn bạn, quan điểm của bạn về :: là một cấu trúc đặc biệt là chính xác những gì tôi đã không rõ ràng về. Tôi đã thử sử dụng các toán tử khác trong mẫu phù hợp với cách "giống nhau", nhưng nó không có ý nghĩa gì nhiều và tôi không biết đâu, đó là điều khiến tôi băn khoăn về khuyết điểm. – Mathias

+1

Lưu ý rằng điều tương tự cũng đúng đối với Tuples - bạn có thể sử dụng mẫu (,) để xây dựng và kết hợp/giải nén tuples, và đối với các loại khác (Some()/None) v.v. – Benjol

+0

Đây là danh sách [tất cả được hỗ trợ kiểu mẫu] (https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching) với các ví dụ. – JanDotNet

13

Đó là cú pháp đặc biệt cho danh sách. Bạn có thể nghĩ đến loại list như một sự kết hợp kỳ thị thusly:

type list<'T> =   // ' 
    | Nil 
    | Cons of 'T * list<'T> 

ngoại trừ việc có cú pháp đặc biệt mà làm cho Nil được []Cons(h,t) được h::t. Sau đó, nó chỉ là mô hình phù hợp bình thường trên một công đoàn phân biệt đối xử. cái đó có giúp ích không?

(Có thể xem thêm this blog entry.)

+0

Rất hữu ích, cảm ơn bạn! – Mathias

2

Nó được sử dụng như một định dạng hoặc chính thức pattern, `danh sách' là lần xuất hiện với ba mô hình:

[] có nghĩa là danh sách là rỗng

[_] có nghĩa là danh sách có một phần tử, vì bạn không quan tâm đến phần tử là gì, vì vậy chỉ cần đặt _ ở đó, bạn cũng có thể sử dụng [a].

đầu :: đuôi có nghĩa là danh sách không có hai phần: đầu và đuôi.

Bạn có thể xem kết hợp mẫu F # dưới dạng cấu trúc mạnh mẽ nếu sau đó khác.

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