2012-04-18 33 views
11

tôi nhận thấy rằng đoạn mã sau đưa ra một thông báo lỗi khi bạn cố gắng để biên dịch nó:Tại sao trình xây dựng tính toán seq không cho phép "cho phép!"

let xx = 
    seq { 
    let! i = [ 1; 2 ] 
    let! j = [ 3; 4 ] 
    yield (i,j) 
    } 

Các lỗi này sẽ cho là "lỗi FS0795: '! Hãy để x = coll' Việc sử dụng trong các biểu thức chuỗi là không Sử dụng 'for x in coll' thay thế. "Thông báo này tất nhiên là rõ ràng và thể hiện cách khắc phục nó; mã cố định sẽ là:

let xx = 
    seq { 
    for i in [ 1; 2 ] do 
     for j in [ 3; 4 ] do 
     yield (i,j) 
    } 

Câu hỏi của tôi không phải là cách khắc phục điều này, nhưng tại sao "cho phép!" không được phép trong các biểu thức trình tự ở nơi đầu tiên? Tôi có thể thấy thực tế là như thế nào! lặp lại qua một biểu thức có thể gây ngạc nhiên cho một số người, nhưng điều đó không đủ để không cho phép cấu trúc. Tôi cũng thấy cách "for" mạnh hơn ở đây, như phiên bản với "let!" bakes trong phạm vi của iteration là "cho đến khi kết thúc của biểu thức trình tự".

Tuy nhiên, việc có thể lặp qua một chuỗi mà không cần phải thụt lề mã là chính xác những gì tôi đang tìm kiếm (để duyệt qua cấu trúc cây). Tôi cho rằng để có được ngữ nghĩa này, tôi sẽ phải tạo một trình tạo biểu thức mới hoạt động chủ yếu giống như trình tạo biểu thức "seq", nhưng cho phép "cho phép!" cho lặp lại, phải không?


gia tăng, dựa trên nhận xét của Brian bên dưới, cung cấp giải pháp cho vấn đề tiềm ẩn của tôi:

Tôi đã không nhận ra sự thụt vào trong cho khối là không cần thiết, và lần thứ hai mẫu có thể được viết lại là:

let xx = 
    seq { 
    for i in [ 1; 2 ] do 
    for j in [ 3; 4 ] do 
    yield (i,j) 
    } 

... loại bỏ sự thụt đầu dòng ngày càng tăng khi di chuyển qua cấu trúc cây. Cú pháp thậm chí cho phép báo cáo bổ sung trong giữa cho báo cáo mà không đòi hỏi thêm thụt đầu dòng, như trong:

let yy = 
    seq { 
    for i in [ 1; 2 ] do 
    let i42 = i+42 
    for j in [ 3; 4 ] do 
    yield (i42,j) 
    } 

Bây giờ, nếu duy nhất tôi có thể tìm ra lý do tại sao tôi nghĩ rằng các báo cáo này sẽ đòi hỏi thụt đầu dòng ...

+4

sự nhầm lẫn có thể xảy ra với 'cho phép! 'Trong các liên kết không đồng bộ - chúng ta có cú pháp giống hệt nhau làm những việc hoàn toàn khác nhau? –

+1

Bạn đã thử 'vì không có indents? – Brian

+0

@Brian "Bạn đã thử 'vì không có indents?" - Không, vì một lý do nào đó mà tôi không nhận ra được các indents trong 'for's là không cần thiết. Cám ơn vì sự gợi ý! Nói đúng ra nó không trả lời câu hỏi, nhưng cung cấp một công việc có thể chấp nhận được, vì vậy theo cách nó trả lời câu hỏi của tôi. –

Trả lời

8

Chỉ một vài tuần trước, tôi đã viết một bài báo với Don Syme, cố gắng giải thích một số động lực đằng sau các lựa chọn cú pháp trong biểu thức tính toán F # (như biểu thức trình tự, quy trình công việc không đồng bộ và các biểu thức khác). Bạn có thể find it here. Nó không đưa ra câu trả lời rõ ràng cho câu hỏi của bạn, nhưng nó có thể hữu ích.

Nói chung, khi bạn có một số loại M<'T> và bạn đang định xây dựng tính toán, bạn có thể thêm các phương pháp ForBind để cho phép forlet! cú pháp:

For : seq<'T> -> ('T -> M<'T>) -> M<'T> 
Bind : M<'T> -> ('T -> M<'T>) -> M<'T> 

Các đầu vào cho For nên luôn luôn có một số trình tự seq<'T>, trong khi đầu vào cho Bind phải là loại M<'T> mà bạn đang xác định nó.

Trong biểu thức trình tự, hai thao tác này sẽ có cùng loại và do đó chúng sẽ phải thực hiện tương tự. Mặc dù các biểu thức trình tự có thể cung cấp cả hai, nhưng có thể là một ý tưởng hay khi chỉ cho phép một, bởi vì sử dụng hai từ khóa khác nhau cho một điều sẽ gây nhầm lẫn.Một nguyên tắc chung là mã trong khối comp { .. } sẽ hoạt động như mã bình thường - và vì for tồn tại trong mã F # bình thường, nên sử dụng cùng cú pháp bên trong biểu thức tính toán cho seq<'T>.

+1

Cảm ơn bạn đã giải thích! Cá nhân tôi nghĩ rằng tôi sẽ để lại cả hai tùy chọn cú pháp, vì chuyến tàu tư tưởng dẫn đến mỗi tùy chọn có thể khác nhau, ngay cả khi chúng hoạt động giống nhau. Trong trường hợp của tôi, tôi đang tìm kiếm một hoạt động đã khớp với chữ ký Bind M <'T> có thể đại diện cho một số loại bộ sưu tập 'T. Sau đó tôi nhận ra rằng cũ seq <'T> đã làm mọi thứ tôi cần, vì vậy tôi đã cố gắng sử dụng Bind của seq {...}, có nghĩa là viết "let!" bên trong biểu thức seq {...}. Đó là nơi tôi gặp phải thông báo lỗi ... –

+2

Giấy đẹp, Tomas! – Daniel

+1

Liên kết tới bài báo hiện đang cung cấp 404, có cách nào khác để tìm nó không? – VisualMelon

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