2009-06-24 27 views
7

Tôi đã chơi xung quanh với F # (Visual Studio 2010 beta 1), và tôi đã viết một kịch bản giao diện điều khiển nhỏ yêu cầu người dùng nhập 2 số và một nhà điều hành và sau đó thực hiện nó. Nó hoạt động tốt, ngoài một điều nhỏ nhặt, nhưng gây phiền nhiễu: đôi khi các lệnh printfn của tôi bị bỏ qua. Tôi đặt các điểm ngắt trong mã để xem đó thực sự là trường hợp.F # lạ printfn vấn đề

Đoạn mã:

let convert (source : string) = 
    try System.Int32.Parse(source) 
    with :? System.FormatException -> 
     printfn "'%s' is not a number!" source; 
     waitForExitKey(); 
     exit 1 

let read = 
    printfn "Please enter a number."; 
    System.Console.ReadLine 

let num1 : int = read() |> convert // the printfn in the read function is run... 
let num2 : int = read() |> convert // ... but here is ignored 

Đây không phải là nguồn hoàn chỉnh tất nhiên, nhưng tôi nghĩ rằng sẽ là đủ. Nếu bạn cần nguồn hoàn chỉnh, hãy cho tôi biết.

Vì vậy, câu hỏi của tôi khá đơn giản: nguyên nhân gây ra vấn đề này với printfn? Tôi có làm điều gì sai?

Cảm ơn trước, ShdNx

Trả lời

15

This page có một lời giải thích một phần của những gì đang xảy ra, nhưng phiên bản ngắn và ngọt ngào là F # sẽ thực hiện bất kỳ giá trị nào trên khai báo nếu nó không nhận tham số.

let read = 
    printfn "Please enter a number." 
    System.Console.ReadLine 

Kể từ read không mất bất kỳ thông số, thực hiện nó ngay lập tức trên tờ khai và liên kết với các giá trị trả về của hàm để nhận dạng read.

Ngẫu nhiên, giá trị trả về của bạn xảy ra là một hàm có loại (unit -> string). Điều này là do F # tự động curries functions nếu chúng không được chuyển tất cả các tham số của chúng. ReadLine mong đợi một tham số đơn vị, nhưng vì nó không được truyền, bạn thực sự liên kết read với chính hàm ReadLine.

Giải pháp là như sau:

let read() = // read takes one unit parameter 
    printfn "Please enter a number." 
    System.Console.ReadLine() // pass paramter to ReadLine method 

Kể từ read mất một tham số, tái thẩm của nó mỗi lần gọi của nó. Ngoài ra, chúng tôi đang chuyển một tham số đến ReadLine, nếu không, chúng tôi sẽ chỉ trả lại hàm ReadLine làm giá trị.

+0

Cảm ơn bạn rất nhiều! Thật không may Ray nhanh hơn, nên tôi chấp nhận câu trả lời của anh ta. Nhưng tôi vẫn rất vui vì bạn đã làm rõ điều này. Cảm ơn một lần nữa! – ShdNx

+0

Tôi đồng ý! 1 cho một lời giải thích rõ ràng hơn! –

7

Tôi hiểu rằng điều này có thể gây nhầm lẫn. Trong ví dụ của bạn, printfn chạy sớm hơn bạn nghĩ. Nó sẽ thực sự thực thi ngay cả khi không có cuộc gọi đến read(), tức là, nhận xét hai dòng cuối cùng và bạn sẽ vẫn thấy một thông báo đang được in.

Tôi nghĩ rằng ý định của bạn là một cái gì đó như thế này:

let read() = 
    printfn "Please enter a number."; 
    System.Console.ReadLine() 

này sẽ tạo ra một "tái sử dụng" chức năng thay vì ràng buộc một chức năng để một định danh như trong ví dụ ban đầu của bạn.

Là một sidenote, việc sử dụng dấu chấm phẩy ở đây là không bắt buộc vì vậy bạn chỉ có thể viết:

let read() = 
    printfn "Please enter a number." 
    System.Console.ReadLine() 
+0

Cảm ơn bạn rất nhiều, tôi nghĩ tôi đã hiểu nó ngay bây giờ! Tôi sử dụng dấu chấm phẩy vì tôi tự động thêm dấu chấm phẩy sau mỗi dòng và nó làm phiền tôi nếu tôi không thể thấy bất kỳ ... :-) – ShdNx

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