Điều gì trong lập trình chức năng tạo nên sự khác biệt?
Lập trình chức năng là theo nguyên tắc khai báo . Bạn nói gì kết quả của bạn là thay vì cách tính toán nó.
Chúng ta hãy xem thực hiện chức năng thực sự của đoạn trích của bạn. Trong Haskell, nó sẽ là:
predsum pred numbers = sum (filter pred numbers)
Là nó rõ ràng những gì kết quả là? Khá là như vậy, nó là tổng của các số đáp ứng vị ngữ. Nó được tính như thế nào? Tôi không quan tâm, hãy hỏi trình biên dịch.
Bạn có thể nói rằng sử dụng sum
và filter
là một mẹo và nó không được tính. Hãy thực hiện nó mà không có những người trợ giúp này sau đó (mặc dù cách tốt nhất sẽ là thực hiện chúng trước).
Giải pháp "Lập trình chức năng 101" không sử dụng sum
là với đệ quy:
sum pred list =
case list of
[] -> 0
h:t -> if pred h then h + sum pred t
else sum pred t
Nó vẫn còn khá rõ ràng những gì kết quả về cuộc gọi chức năng duy nhất là. Nó là 0
, hoặc recursive call + h or 0
, tùy thuộc vào pred h
. Vẫn còn khá căng thẳng, ngay cả khi kết quả cuối cùng không rõ ràng ngay lập tức (mặc dù với một chút thực hành, điều này thực sự đọc giống như một for
vòng lặp).
So sánh với phiên bản của bạn:
public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
int result = 0;
foreach(var item in numbers)
if (predicate(item)) result += item;
return result;
}
Kết quả là gì? Ồ, tôi thấy: return
tuyên bố duy nhất , không có gì ngạc nhiên ở đây : return result
.
Nhưng là result
gì? int result = 0
? Có vẻ không đúng. Bạn làm một cái gì đó sau đó với điều đó 0
. Ok, bạn thêm item
s vào nó. Và như thế.
Tất nhiên, đối với hầu hết các lập trình viên, điều này khá rõ ràng những gì xảy ra trong một funciton đơn giản như thế này, nhưng thêm một số return
câu lệnh bổ sung hoặc như vậy và nó đột nhiên trở nên khó theo dõi hơn. Tất cả các mã là về làm thế nào , và những gì còn lại để người đọc tìm ra - đây rõ ràng là một phong cách rất bắt buộc .
Vì vậy, các biến và vòng lặp sai?
Không.
Có nhiều điều dễ giải thích hơn nhiều bởi chúng, và nhiều thuật toán yêu cầu trạng thái có thể thay đổi phải nhanh. Nhưng các biến vốn là bắt buộc, giải thích làm thế nào thay vì cái gì và đưa ra dự đoán nhỏ về giá trị của chúng có thể là một vài dòng sau hoặc sau một vài lần lặp. Các vòng lặp thường yêu cầu trạng thái có ý nghĩa, và do đó chúng cũng bắt buộc.
Các biến và vòng lặp đơn giản là không lập trình chức năng.
Tóm lược
Lập trình funcitonal đương thời là một chút phong cách và một cách suy nghĩ hữu ích hơn một mô hình. Sở thích mạnh mẽ cho các chức năng thuần túy là trong suy nghĩ này, nhưng thực tế nó chỉ là một phần nhỏ.
Hầu hết các ngôn ngữ phổ biến cho phép bạn sử dụng một số cấu trúc chức năng. Ví dụ: trong Python bạn có thể chọn giữa:
result = 0
for num in numbers:
if pred(result):
result += num
return result
hoặc là
return sum(filter(pred, numbers))
hoặc là
return sum(n for n in numbers if pred(n))
Các biểu thức chức năng này phù hợp độc đáo cho các vấn đề loại đó và chỉ cần làm cho mã ngắn hơn (và ngắn hơn là tốt ). Bạn không nên thay thế mã bắt buộc bằng chúng, nhưng khi chúng phù hợp, chúng hầu như luôn là lựa chọn tốt hơn.
item
biến bị đột biến trong vòng lặp.