Vâng, có cả hai có sẵn thay vì chỉ có một cho phép lập trình kiểm soát chặt chẽ hơn trên phạm vi. Với let x = e1 in e2
, sự ràng buộc chỉ xuất hiện trong môi trường của e2
, trong khi với let rec x = e1 in e2
ràng buộc có mặt trong cả hai môi trường e1
và e2
.
(Edit: Tôi muốn nhấn mạnh rằng đó là không một vấn đề hiệu suất, mà làm cho có sự khác biệt nào cả.)
Dưới đây là hai tình huống mà có này ràng buộc phi đệ quy là hữu ích:
che giấu định nghĩa hiện tại bằng tinh lọc sử dụng liên kết cũ. Một cái gì đó như: let f x = (let x = sanitize x in ...)
, trong đó sanitize
là một hàm đảm bảo đầu vào có một số thuộc tính mong muốn (ví dụ: nó lấy chuẩn của một vectơ có thể không chuẩn hóa, v.v.). Điều này rất hữu ích trong một số trường hợp.
lập trình meta, ví dụ như viết macro. Hãy tưởng tượng tôi muốn xác định một macro SQUARE(foo)
mà desugars vào let x = foo in x * x
, cho bất kỳ biểu thức foo
. Tôi cần sự ràng buộc này để tránh trùng lặp mã trong đầu ra (tôi không muốn SQUARE(factorial n)
để tính factorial n
hai lần). Điều này chỉ hợp vệ sinh nếu ràng buộc let
không đệ quy, nếu không tôi không thể viết let x = 2 in SQUARE(x)
và nhận kết quả chính xác.
Vì vậy, tôi cho rằng điều rất quan trọng là phải có cả ràng buộc đệ quy và không đệ quy. Bây giờ, hành vi mặc định của sự ràng buộc là một vấn đề của quy ước. Bạn có thể nói rằng let x = ...
là đệ quy, và người ta phải sử dụng let nonrec x = ...
để có được chất kết dính không đệ quy. Chọn một mặc định hoặc khác là một vấn đề mà phong cách lập trình bạn muốn ủng hộ và có những lý do tốt để thực hiện một trong hai lựa chọn. Haskell bị lỗi do không có chế độ không đệ quy này và OCaml có lỗi chính xác ở mức loại: type foo = ...
là đệ quy và không có tùy chọn không đệ quy - xem this blog post.
¹: khi Google Code Search có sẵn, tôi đã sử dụng nó để tìm kiếm trong mã Haskell cho mẫu let x' = sanitize x in ...
. Đây là cách giải quyết thông thường khi không có sự ràng buộc không đệ quy, nhưng ít an toàn hơn vì bạn có nguy cơ viết x
thay vì x'
do nhầm lẫn sau này - trong một số trường hợp bạn muốn có sẵn, vì vậy hãy chọn một tên khác có thể là tự nguyện . Thành ngữ tốt sẽ là sử dụng tên biến dài hơn cho x
đầu tiên, chẳng hạn như unsanitized_x
. Dù sao, chỉ cần tìm kiếm x'
trên mặt đất (không có tên biến khác) và x1
đã chuyển rất nhiều kết quả. Erlang (và tất cả các ngôn ngữ mà cố gắng làm cho biến bóng khó khăn: Coffeescript, vv) có vấn đề thậm chí còn tồi tệ hơn của loại hình này.
Điều đó nói rằng, sự lựa chọn có ràng buộc Haskell đệ quy theo mặc định (chứ không phải đệ quy) chắc chắn có ý nghĩa, vì nó phù hợp với đánh giá lười biếng theo mặc định, giúp dễ dàng xây dựng các giá trị đệ quy. -ngôn ngữ mặc định có nhiều hạn chế hơn về định nghĩa đệ quy nào có ý nghĩa.
Tại sao phiếu bầu đóng lại ..? Có vẻ như một câu hỏi hợp lý. – Sean
Xem http://stackoverflow.com/questions/900585/why-are-functions-in-ocaml-f-not-recursive-by-default –
@Sean: đây là một câu hỏi thường gặp. – Ashe