Tôi hoàn toàn mới đối với F # (và lập trình hàm nói chung) nhưng tôi thấy kết hợp mẫu được sử dụng ở mọi nơi trong mã mẫu. Tôi tự hỏi ví dụ làm thế nào mô hình phù hợp với thực sự hoạt động? Ví dụ, tôi tưởng tượng nó hoạt động giống như vòng lặp for trong các ngôn ngữ khác và kiểm tra các kết quả phù hợp trên mỗi mục trong một bộ sưu tập. Điều này có lẽ là xa chính xác, làm thế nào nó thực sự làm việc đằng sau hậu trường?Làm thế nào để phù hợp với mô hình làm việc đằng sau hậu trường trong F #?
Trả lời
Nó phụ thuộc vào loại kết hợp mẫu nào bạn muốn nói - nó có cấu trúc khá mạnh và có thể được sử dụng theo mọi cách. Tuy nhiên, tôi sẽ cố gắng giải thích cách khớp mẫu hoạt động trên danh sách. Bạn có thể viết ví dụ những mẫu:
match l with
| [1; 2; 3] -> // specific list of 3 elements
| 1::rest -> // list starting with 1 followed by more elements
| x::xs -> // non-empty list with element 'x' followed by a list
| [] -> // empty list (no elements)
Chiếc F # danh sách thực sự là một sự kết hợp kỳ thị có chứa hai trường hợp - []
đại diện cho một danh sách rỗng hoặc x::xs
đại diện cho một danh sách với phần tử đầu tiên x
sau bởi một số yếu tố khác. Trong C#, điều này có thể được biểu diễn như thế này:
// Represents any list
abstract class List<T> { }
// Case '[]' representing an empty list
class EmptyList<T> : List<T> { }
// Case 'x::xs' representing list with element followed by other list
class ConsList<T> : List<T> {
public T Value { get; set; }
public List<T> Rest { get; set; }
}
Các mô hình trên sẽ được biên dịch như sau (tôi đang sử dụng pseudo-code để làm đơn giản này):
if (l is ConsList) && (l.Value == 1) &&
(l.Rest is ConsList) && (l.Rest.Value == 2) &&
(l.Rest.Rest is ConsList) && (l.Rest.Rest.Value == 3) &&
(l.Rest.Rest.Rest is EmptyList) then
// specific list of 3 elements
else if (l is ConsList) && (l.Value == 1) then
var rest = l.Rest;
// list starting with 1 followed by more elements
else if (l is ConsList) then
var x = l.Value, xs = l.Rest;
// non-empty list with element 'x' followed by a list
else if (l is EmptyList) then
// empty list (no elements)
Như bạn có thể thấy, không có vòng lặp liên quan. Khi xử lý danh sách trong F #, bạn sẽ sử dụng đệ quy để thực hiện vòng lặp, nhưng khớp mẫu được sử dụng trên các phần tử riêng lẻ (ConsList
) cùng nhau tạo toàn bộ danh sách.
Kết hợp mẫu trên danh sách là trường hợp cụ thể của công đoàn phân biệt được thảo luận bởi sepp2k. Có các cấu trúc khác có thể xuất hiện trong kết hợp mẫu, nhưng về cơ bản tất cả chúng được biên dịch bằng cách sử dụng câu lệnh if
phức tạp (phức tạp).
Không, nó không lặp lại. Nếu bạn có một mô hình phù hợp như thế này
match x with
| Foo a b -> a + b
| Bar c -> c
này biên dịch xuống một cái gì đó giống như mã giả này:
if (x is a Foo)
let a = (first element of x) in
let b = (second element of x) in
a+b
else if (x is a Bar)
let c = (first element of x) in
c
Nếu Foo và Bar là nhà xây dựng từ một kiểu dữ liệu đại số (ví dụ: một loại được xác định như type FooBar = Foo int int | Bar int
) các hoạt động x is a Foo
và x is a Bar
là các so sánh đơn giản. Nếu chúng được xác định bởi một active pattern, các hoạt động được xác định bởi mẫu đó.
Cách đối sánh mẫu thực sự hoạt động? Giống như một vòng lặp
for
?
Đó là về như xa một vòng lặp for
như bạn có thể tưởng tượng: thay vì vòng lặp, một mô hình phù hợp là biên soạn để một automaton hiệu quả. Có hai kiểu automaton, cái mà tôi gọi là "cây quyết định" và "kiểu Pháp". Mỗi kiểu có các ưu điểm khác nhau: cây quyết định kiểm tra số lượng tối thiểu cần thiết để đưa ra quyết định, nhưng việc triển khai ngây thơ có thể yêu cầu không gian mã theo cấp số nhân trong trường hợp xấu nhất. Phong cách Pháp cung cấp một sự cân bằng không gian thời gian khác nhau, với sự đảm bảo tốt nhưng không tối ưu cho cả hai.
Nhưng công việc hoàn toàn dứt khoát về vấn đề này là giấy tuyệt vời của Luc Maranget "Compiling Pattern Matching to Good Decisions Trees từ Hội thảo ML 2008. Giấy của Luc về cơ bản cho thấy làm thế nào để có được tốt nhất của cả hai thế giới. Nếu bạn muốn điều trị có thể dễ tiếp cận hơn với người chuyên nghiệp, tôi khiêm tốn đề nghị cung cấp của riêng tôi When Do Match-Compilation Heuristics Matter?
Viết trình biên dịch khớp mẫu thật dễ dàng và thú vị!
Thú vị. Tôi tự hào trả thuế để các quan tài INRIA có thể tìm ra cách tốt nhất để biên dịch mẫu phù hợp :) – Stringer
@Stringer: Luc Maranget là một quan tài tốt. –
Tham khảo tuyệt vời, cảm ơn! –
Nếu bạn biên dịch mã F # thành .exe thì hãy xem Reflector bạn có thể xem C# "tương đương" của mã F #.
Tôi đã sử dụng phương pháp này để xem xét các ví dụ về F # một chút.
- 1. Làm thế nào để tăng cường ràng buộc làm việc đằng sau hậu trường nói chung?
- 2. Đằng sau hậu trường: ORM "suy nghĩ" như thế nào?
- 3. Loại serialization nào sử dụng Wcf đằng sau hậu trường?
- 4. Hoạt động đằng sau hậu trường trên nhắc tải python
- 5. Làm thế nào để phù hợp với mô hình một lớp lồng nhau trong Scala?
- 6. Haskell mô hình phù hợp với trường hợp đối xứng
- 7. Quy trình Erlang đằng sau hậu trường là gì?
- 8. ngắn gọn mô hình phù hợp trên trường hợp duy nhất bị kỳ thị công đoàn trong F #
- 9. Linq hoạt động như thế nào (phía sau hậu trường)?
- 10. Tạo mô hình với trường hợp Scala
- 11. F # mô hình kết hợp kỳ quặc
- 12. Làm thế nào để tail -f file log mới nhất với một mô hình cho
- 13. Typekit hoạt động như thế nào sau hậu trường?
- 14. Chuỗi mô hình phù hợp với vấn đề trong Java
- 15. Làm thế nào để xóa các tập tin phù hợp với mô hình trong một thư mục
- 16. Khuôn khổ thực thể: Tuần tự hóa/Deserialize cột JSON đằng sau hậu trường
- 17. Truy vấn Nhóm LINQ Lớn, những gì đang diễn ra đằng sau hậu trường
- 18. Variable trong xsl: template phù hợp với mô hình
- 19. Làm thế nào để tạo ra một mô hình với một trường kiểu enum?
- 20. REST có phù hợp với các mô hình 3NF lớn
- 21. Làm thế nào để mô hình chu kỳ giữa các trường hợp lớp không thay đổi?
- 22. OrderBy trong LINQ hoạt động như thế nào (sau hậu trường)?
- 23. Ai đó có thể giải thích những gì đang diễn ra đằng sau hậu trường?
- 24. Có cách nào để phù hợp với mô hình như vậy với vỏ hoặc sed?
- 25. Làm thế nào để phù hợp với hình ảnh trong div wather kích thước hình ảnh là tối đa sau đó div hoặc min sau đó div
- 26. Làm thế nào để xóa các dòng phù hợp với một mô hình và các dòng sau khi nó với sed?
- 27. mô hình có điều kiện phù hợp trong vợt
- 28. Làm thế nào để thay thế chỉ toàn bộ từ phù hợp trong Vim?
- 29. Phù hợp với hậu duệ thứ bậc phù hợp với bộ chọn jQuery
- 30. Làm thế nào để bạn làm việc với nhiều mô hình trong Ember JS (không có Dữ liệu Ember)?
Tôi tin rằng bạn đã quên đặt EmptyList và ConsList được kế thừa từ Danh sách trừu tượng . Có thể gây nhầm lẫn cho ai đó ... –
@Johan: Vâng, thực sự! Cảm ơn! –