2010-09-17 37 views
14

Tôi không chắc chắn nếu điều này là một câu hỏi ngu ngốc nhưng tôi đã trải qua những hướng dẫn mà đi kèm với VS 2010 và có một chức năng như thế này:Lý do đánh dấu chức năng đệ quy là rec trong F #?

let rec factorial n = if n=0 then 1 else n * factorial (n-1) 

là gì lý do của hàm đệ quy này phải được đánh dấu với từ khóa rec?

Có phải trình biên dịch được đảm bảo là đệ quy để có thể thực hiện tối ưu hóa nhất định không?

Điều gì xảy ra nếu bạn loại trừ nó?

+0

Có thể trùng lặp? http://stackoverflow.com/questions/900585/why-are-functions-in-ocaml-f-not-recursive-by-default – Stringer

+1

Cảm ơn họ có vẻ tương tự, cũng sẽ đọc nó. –

Trả lời

27

Đây có thể là bài học:

let Main() = 
    let f(x) = 
     printfn "original f: %d" x 
    let f(x) = 
    //let rec f(x) = 
     printfn "entered new f: %d" x 
     if x > 0 then 
      f(x-1) 
     else 
      printfn "done" 
    f(3) 
Main() 

Đó in

entered new f: 3 
original f: 2 

Bây giờ nếu chúng ta nhận xét ra let và bỏ ghi chú let rec, sau đó nó in

entered new f: 3 
entered new f: 2 
entered new f: 1 
entered new f: 0 
done 

Vì vậy, từ quan điểm đó xem, nó chỉ là về ràng buộc tên; let rec đặt số nhận dạng trong phạm vi ngay lập tức (trong ví dụ này, che khuất f trước đó), trong khi let đặt số nhận dạng trong phạm vi chỉ sau khi nội dung của nó được xác định.

Động lực cho quy tắc xuất phát từ các tương tác với suy luận kiểu.

+2

Đó là một ví dụ rất mang tính giáo dục về ràng buộc, che khuất và phạm vi :-). –

+3

+1 nhưng "Động lực cho quy tắc không xuất phát từ các tương tác với suy luận kiểu" có thể làm với một số làm rõ. –

8

Theo MSDN, nó chỉ là một sự cần thiết syntatic:

chức năng đệ quy, chức năng mà gọi bản thân, được xác định một cách rõ ràng trong F # ngôn ngữ. Điều này làm cho số nhận dạng đang được được xác định có sẵn trong phạm vi chức năng .

http://msdn.microsoft.com/en-us/library/dd233232.aspx

+0

+1 là câu trả lời duy nhất ở đây để có được điều này đúng. –

11

Theo Chris Smith (chỉ hoạt động trên # nhóm F) -

Đó là thông báo cho hệ thống kiểu suy luận để cho phép các chức năng sẽ được sử dụng như là một phần của quá trình suy luận kiểu. rec cho phép bạn gọi hàm trước khi hệ thống suy luận loại đã xác định loại của hàm

+0

Nếu không thì hệ thống suy luận loại sẽ đi vào vòng lặp vô hạn? Nếu đó là lý do tại sao, sau đó có ý nghĩa. –

+1

Thực sự, đó là tất cả? Lấy điểm này vào, tôi tự hỏi liệu tôi có thể viết một hàm đệ quy * mà không có * 'rec' nếu tôi định nghĩa rõ ràng tất cả các kiểu ... thời gian thử nghiệm! – sholsapp

+4

Không có 'rec', bạn cũng phải tự định nghĩa hàm đó trước. Nhưng bạn phải định nghĩa hàm đầu tiên, vì nó sẽ không có sẵn trong phạm vi riêng của nó. Nhưng trước tiên, bạn phải xác định hàm. Sau khi bạn đã xác định hàm. Khi hàm đã được xác định. Mà sẽ yêu cầu xác định chức năng. * ad infinitum. * – cHao

5

Cần thiết để hàm có thể được đệ quy. Hàm không phải là rec chỉ biết về các ràng buộc tại nơi nó được xác định, chứ không phải sau (vì vậy nó không biết về chính nó).

+0

Cảm ơn Chuck. Bạn có ý nghĩa gì bởi các ràng buộc? Nó giống như phạm vi? –

+3

@Janan Venge: một ràng buộc về cơ bản là một tên biến và giá trị liên quan của nó. Trong trường hợp này nó có nghĩa là bạn không thể sử dụng hàm bên trong chính nó, vì nó chỉ bị ràng buộc với tên * sau * 'let'. 'let rec' làm cho các tên đang bị ràng buộc có sẵn * bên trong * biểu thức ràng buộc. –

+0

@Jorg, cảm ơn điều đó có ý nghĩa. –

4

Lý do của hàm đệ quy này được đánh dấu bằng từ khóa rec là gì?

Để cho trình biên dịch biết rằng bất kỳ cách sử dụng nào của tên hàm bên trong nội dung của hàm tham chiếu đệ quy thay vì giá trị được xác định trước đó của cùng một tên.

Có phải trình biên dịch được đảm bảo là đệ quy để có thể thực hiện tối ưu hóa nhất định không?

số

gì sẽ xảy ra nếu bạn loại trừ nó?

Bạn mất khả năng cho hàm bạn định xác định tham chiếu trong thân hàm và có khả năng tham chiếu đến các giá trị được xác định trước đó của cùng một tên.

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