2013-07-26 19 views

Trả lời

11

Trước khi trả lời những gì () cho phép nhận được một số khái niệm cơ bản được xác định và một số ví dụ được thực hiện.

Trong F # a let statement có tên, không hoặc nhiều đối số và biểu thức.

Để đơn giản hóa chúng tôi sẽ thực hiện:
Nếu không có đối số thì tuyên bố let là value.
Nếu có đối số thì câu lệnh let là function.

Đối với một giá trị, kết quả của biểu thức chỉ được đánh giá một lần và được liên kết với số nhận dạng; nó là bất biến.
Đối với một hàm, biểu thức được đánh giá mỗi lần hàm được gọi.

Vì vậy, đây giá trị

let a = System.DateTime.Now;; 

sẽ luôn có thời gian khi nó lần đầu tiên được đánh giá hay muộn gọi, tức là

a;; 
val it : System.DateTime = 1/10/2017 8:16:16 AM ... 
a;; 
val it : System.DateTime = 1/10/2017 8:16:16 AM ... 
a;; 
val it : System.DateTime = 1/10/2017 8:16:16 AM ... 

chức năng này

let b() = System.DateTime.Now;; 

sẽ alwa y có thời gian mới mỗi khi được đánh giá, tức là

b();; 
val it : System.DateTime = 1/10/2017 8:18:41 AM ... 
b();; 
val it : System.DateTime = 1/10/2017 8:18:49 AM ... 
b();; 
val it : System.DateTime = 1/10/2017 8:20:32 AM ... 

Bây giờ để giải thích ý nghĩa của (). Lưu ý rằng System.DateTime.Now không cần đối số để hoạt động.

Làm cách nào để tạo hàm khi biểu thức không cần đối số?

Mọi đối số đều phải có loại, vì vậy F # có unit type cho các hàm không cần đối số và giá trị duy nhất cho loại đơn vị là ().

Vì vậy, đây là một chức năng với một đối số x loại int

let c x = x + 1;; 

và đây là một chức năng với một đối số () loại unit

let b() = System.DateTime.Now;; 
+0

Đơn giản chỉ cần đặt, nó chỉ là một hình thức F # chức năng gọi mà không có tham số? – Fabricio

+1

@Fabricio Có. Nhưng tôi đã thêm một cái gì đó để vượt qua tối thiểu 15 ký tự cho một bình luận. –

+0

@Fabricio: Tôi sẽ không nói điều đó. 'b' ở đây là một hàm nhận tham số * one *:' unit'. Nếu bạn cố gắng gọi nó mà không có dấu ngoặc đơn, bạn sẽ nhận được * giá trị hàm * 'b' thay vì kết quả * của hàm' b' *. Hãy thử 'let d = b ;; d() ;; 'trong FSI. –

4

Sử dụng () tạo hàm có tham số loại unit, thay vì trường hợp thứ hai chỉ là một số nguyên đơn giản.

Điều này đặc biệt quan trọng khi bạn muốn kiểm soát việc thực hiện chức năng.

Sự khác biệt chính là khi bạn có

let name() = 
    printfn "hello" 
    1 

vs

let name = 
    printfn "hello" 
    1 

sau đó

let t = name + name 

sẽ in "hello" một lần. Nhưng

let t = (name()) + (name()) 

sẽ in "hello" hai lần.

Bạn phải cẩn thận với điều này khi xem xét thứ tự các hàm được đánh giá.

Hãy xem xét các chương trình sau đây:

let intversion = 
    printfn "creating integer constant" 
    1 

printfn "integer created" 

let funcversion() = 
    printfn "executing function" 
    1 

printfn "function created" 

let a = intversion + intversion 
printfn "integer calculation done" 
let b = (funcversion()) + (funcveriosn()) 
printfn "function calculation done" 

này sẽ in ra sau theo thứ tự

  1. tạo hằng số nguyên
  2. số nguyên tạo ra
  3. chức năng tạo ra
  4. tính số nguyên làm
  5. thực hiện chức năng
  6. thực hiện chức năng
  7. tính chức năng thực hiện
+0

Tôi nghĩ tôi cần thêm ví dụ. Nó không quá rõ ràng tại sao nó lại quan trọng đến vậy. Dù sao, cái đó là cái gì? – Fabricio

+0

Tôi sẽ thêm một số ví dụ khác. Các '; 1' chúng ta tương đương với một dòng mới và sau đó là 1 để có một giá trị trả về. Tôi chỉ cần đặt nó trong ngắn gọn –

+0

Tôi không có lý do tại sao '" tạo hằng số nguyên "' được in nếu nó chỉ được xác định. – Fabricio

8

Trong

let name() = 3 
name() 

name là một chức năng, kiểu unit -> int.

Trong

let name = 3 
name 

name là một số nguyên, kiểu int.

Trong F #, mọi chức năng đều có kiểu đầu vào và loại đầu ra. Kiểu đầu vào của let name() = 3unit, chỉ có một giá trị ().Loại đầu ra của nó là int, có giá trị từ –2,147,483,648 đến 2,147,483,647. Như một loại ví dụ khác bool chỉ có hai giá trị, truefalse.

Vì vậy, hãy trả lời câu hỏi về cách sử dụng của (). Nếu bạn không chỉ định giá trị đầu vào của một hàm, nó không thể được thực thi. Vì vậy, bạn phải chỉ định một giá trị đầu vào cho hàm let name()=3 của bạn để thực hiện nó và vì kiểu đầu vào của nó là unit, giá trị duy nhất bạn có thể sử dụng là ().

Đây là một cách khác để xác định chức năng và tên:

let name : (unit -> int) = (fun _ -> 3);; 

và so sánh này để:

let name : int = 3 
+0

Nice, cảm ơn! Upvote này cung cấp cho bạn đại diện 10k. :) – Vache

10

chắc chắn không nghĩ về () như một số cú pháp cho một cuộc gọi chức năng hoặc bất cứ điều gì như thế . Nó chỉ là một giá trị, như 3, 5, 'q', sai, hoặc "blah". Giá trị này là một giá trị của loại Unit và trên thực tế nó chỉ là giá trị đơn vị loại của đơn vị loại, nhưng thực sự là bên cạnh điểm. () ở đây là chỉ một giá trị. Tôi không thể nhấn mạnh điều đó.

Đầu tiên xem xét

let name x = 3 

này là gì? Điều này chỉ định nghĩa một hàm trên x, trong đó x có thể là bất kỳ kiểu nào. Trong C# đó sẽ là:

int Name<T>(T x) 
{ 
    return 3; 
} 

Bây giờ nếu chúng ta nhìn vào let name() = 3 (và tôi hơi khuyên bạn nên đặt không gian thêm đó, vì vậy nó làm cho () tìm một giá trị hơn một số cấu trúc cú pháp) sau đó trong C# bạn có thể nghĩ nó như một cái gì đó tương tự (giả)

int Name<T>(T x) where T == Unit //since "()" is the only possible value of Unit 
{ 
    return 3; 
} 

hay đơn giản hơn

int Name(Unit x) 
{ 
    return 3; 
} 

vì vậy, chúng ta thấy rằng tất cả let name() = 3 là, định nghĩa về af unction có một đối số Unit và trả về 3, giống như phiên bản C# ở trên.

Tuy nhiên, nếu chúng tôi xem xét let name = 3 thì đó chỉ là định nghĩa biến, giống như var name = 3 trong C#.