Khi nào sử dụng ngôn ngữ lập trình chức năng?


90

Trong những tình huống nào tôi nên chọn sử dụng ngôn ngữ lập trình chức năng thay vì ngôn ngữ hướng đối tượng dài dòng hơn như C ++, C # hoặc Java?

Tôi hiểu lập trình chức năng là gì, điều tôi không thực sự hiểu là đối với những dạng vấn đề nào thì nó có phải là giải pháp hoàn hảo không?


Câu hỏi này được trả lời ở đây stackoverflow.com/questions/381685/…
krosenvold

2
Luôn luôn. Hoặc ít nhất là không bao giờ.
Shelby Moore III

1
Với lambdas, C # là hàm đường viền.
JD

Câu trả lời:


50

Theo quan điểm của tôi, ngôn ngữ chức năng tốt cho chủ yếu hai thứ: AI trong trò chơi và tính toán toán học. Nó tốt trong trò chơi AI vì các thao tác danh sách đẹp của nó (ít nhất là trong Lisp và Scheme) và cho các phép tính toán học vì cú pháp của nó. Scheme, Lisp và Haskell có một cú pháp giúp các phép tính toán học dễ đọc. Điều cuối cùng tôi phải nói thêm là các ngôn ngữ chức năng là những ngôn ngữ thực sự thú vị. Khóa học Đề án của tôi là một trong những khóa học tôi thấy vui nhất.


2
Sau khi tôi vượt qua thực tế rằng não của tôi muốn nổ tung trong tuần đầu tiên của lớp biên dịch mà tôi tham gia vào Scheme, tôi cũng thấy nó rất thú vị (và tôi đã làm tốt hơn rất nhiều hehe)
Alex Baranosky

1
Bạn đã sử dụng ngôn ngữ chức năng nào để tính toán toán học?
Jules

8
Ngoài ra, trình biên dịch! Tôi đã nghe những người đã viết trình biên dịch trong Haskell nói rằng họ sẽ "không bao giờ viết trình biên dịch bằng một ngôn ngữ bắt buộc nữa".
ShreevatsaR 29/12/08

1
julesjacobs: Tôi đã sử dụng một chút cả haskell và Scheme để giải các phép tính toán học đơn giản. Tôi không giỏi những ngôn ngữ đó, vì vậy tôi có một cách để giải quyết những vấn đề phức tạp hơn. Tôi chỉ không thể làm cho họ đủ nhanh vào lúc này.
martiert

95

Tôi đã tự mình thực hiện một số nghiên cứu về vấn đề này và nghĩ rằng tôi có thể thêm CONCURRENCY vào danh sách các lý do để sử dụng một ngôn ngữ chức năng. Xem tại một số thời điểm trong tương lai gần, tốc độ bộ xử lý sẽ không thể tăng lên khi sử dụng cùng một công nghệ cpu. Vật lý của kiến ​​trúc sẽ không cho phép nó.

Vì vậy, đó là nơi xử lý đồng thời xuất hiện.

Thật không may, hầu hết các ngôn ngữ OOP không thể tận dụng nhiều bộ xử lý cùng một lúc vì sự phụ thuộc lẫn nhau giữa các dữ liệu.

Trong các ngôn ngữ lập trình chức năng thuần túy, máy tính có thể chạy hai (hoặc nhiều) chức năng cùng một lúc vì các chức năng đó không làm thay đổi thông tin trạng thái bên ngoài.

Đây là một bài viết tuyệt vời về lập trình chức năng mà bạn có thể thích.


38
Tôi sẽ không nói rằng hầu hết các ngôn ngữ OO không thể tận dụng một số lượng lớn các bộ xử lý tùy ý. Tôi muốn nói rằng để một chương trình tận dụng được nhiều bộ xử lý cùng lúc một cách hiệu quả và đáng tin cậy, chương trình đó phải được tổ chức sao cho hầu hết các đơn vị mã máy tính chuyên sâu hoạt động giống như các hàm thuần túy. Có thể tổ chức một chương trình theo cách đó với hầu hết các ngôn ngữ. Nó dễ thực hiện trong các ngôn ngữ chức năng hơn so với các ngôn ngữ mệnh lệnh (bao gồm cả hướng đối tượng).
Zak

2
Cảm ơn bạn đã liên kết bài viết đó. Nó thực sự giúp giải thích mọi thứ cho tôi.
guptron

13

Một người bạn của tôi đã dẫn lời một trong những giáo sư đại học của anh ấy nói điều gì đó như sau:

Vẽ lưới với các loại dữ liệu ở trên cùng và các thao tác trên các loại dữ liệu đó ở phía bên trái. Nếu bạn cắt lưới theo chiều dọc, bạn đang thực hiện OO; nếu bạn cắt lưới theo chiều ngang, bạn đang thực hiện FP.

Câu trả lời của tôi là FP là một cách tiếp cận hoàn toàn khả thi để lập trình với nhiều ứng dụng như OO. Như với bất kỳ cuộc thảo luận nào về lựa chọn ngôn ngữ lập trình, tôi nghĩ những câu hỏi quan trọng hơn là:

  1. Bạn có thời gian để đầu tư vào việc học một ký hiệu mới và một cách tư duy mới không?
  2. Ngôn ngữ nào bạn đang xem xét có thư viện đủ phong phú mà bạn sẽ không gặp khó khăn khi phát minh lại bánh xe nào đó?

Đối với câu hỏi đầu tiên, nếu bạn đang làm điều này chủ yếu vì giá trị học tập, tôi khuyên bạn nên xem Haskell , vì có nhiều tài liệu hỗ trợ (sách, bài báo, cộng đồng tích cực, v.v.)

Đối với câu hỏi thứ hai, Haskell có rất nhiều thư viện (mặc dù một số thư viện trưởng thành hơn những thư viện khác), nhưng Scala (một ngôn ngữ chức năng OO kết hợp chạy trên JVM) có những lợi thế mà bạn có thể dần dần chuyển đổi sang phong cách chức năng. và bạn có đầy đủ các thư viện Java có thể truy cập được dành cho bạn.


Tôi đã học Scheme ở trường đại học, vì vậy tôi không muốn học lập trình hàm chỉ để lấy kinh nghiệm. Tôi muốn học một số ngôn ngữ chức năng vì những lý do thực tế.
Alex Baranosky

9

Trên thực tế, mọi thứ bạn có thể làm trong PP đều có thể được thực hiện trong FP và điều tương tự ngược lại. Đó chỉ là một cách khác để viết mã thứ gì đó — một góc nhìn khác về vấn đề và một cách khác để giải quyết nó.

Tuy nhiên, bởi vì không có nhiều người sử dụng FP, vấn đề nằm ở chỗ thiếu thư viện tốt, tính di động / khả năng bảo trì (vì người bảo trì có cơ hội hiểu điều gì đó được viết bằng C ++ hơn là Scheme), và thiếu tài liệu và cộng đồng. Tôi biết có một số tài liệu, tuy nhiên, hãy so sánh tài liệu đó với C ++, C # hoặc Java và bạn sẽ hiểu ý tôi.

Tuy nhiên, nếu bạn thực sự muốn thực hiện FP, bạn có thể sử dụng kiểu này ngay cả trong C ++ và C #. Tất nhiên, nó sẽ không phải là 100% FP nếu bạn sử dụng thư viện tiêu chuẩn. Thật không may, tôi không nghĩ rằng C # được tối ưu hóa để sử dụng với lập trình chức năng và nó có thể sẽ tạo ra nhiều vấn đề về hiệu suất.

Đây là một bài viết chủ quan hơn, những gì tôi nghĩ về FP. Nó không phải là một tuyên bố nghiêm ngặt.


8
"Thực tế mọi thứ bạn có thể làm trong PP đều có thể được thực hiện trong FP" - Thực ra, nó chính xác là mọi thứ.
BlueRaja - Danny Pflughoeft

2
@BlueRaja - bạn đang đề cập đến Turing Completeness? Nếu vậy, những gì bạn nói không tuân theo. Ví dụ: Trò chơi cuộc sống của Conway là Turing Complete, nhưng bạn không thể sử dụng nó để viết trình điều khiển thẻ video như bạn có thể trong C. Tương tự như vậy, tôi không thấy bất kỳ trò chơi mới nhất nào được viết bằng Haskell. Có thể làm trong FP! = Về mặt lý thuyết có thể làm trong FP lý thuyết.
Luigi Plinge

@Luigi Plinge Tôi phải đồng ý với BlueRaja. Haskellers thảo luận về một số trình điều khiển Linux được viết bằng Haskell. Tôi không có liên kết nhưng tôi cũng nghe nói một hệ điều hành đã được viết bằng Haskell (có thể có các ngôn ngữ chức năng khác). Về các trò chơi, tôi không thấy các trò chơi mới nhất được viết bằng C # hoặc Java, bạn có ngụ ý rằng chúng không thể được sử dụng cho việc đó không? Dù sao, một ví dụ về một trò chơi được viết bằng FP. Ngoài ra, hãy nhớ rằng hầu hết các liên kết của tôi là Haskell, một ngôn ngữ chức năng HOÀN TOÀN.
austinprete

@PardonMyRhetoric Rõ ràng là bạn có thể viết trò chơi trong Haskell và thực hiện bất kỳ tính toán nào, nhưng tốc độ sẽ chậm hơn vài lần và sử dụng bộ nhớ cao hơn. Vì vậy, một ví dụ ngược lại với tuyên bố của BlueRaja sẽ là bạn không thể viết "một trò chơi nhanh như và sử dụng nhiều bộ nhớ trong C" trong FP. Đây là một vấn đề thực tế thực sự, không phải là một trò lừa dối trá (và tôi không phải là để phản đối FP - tôi đang viết mã Scala ngay bây giờ!).
Luigi Plinge

1
@PardonMyRhetoric Nó cũng cần phải là FP thành ngữ. Các điểm chuẩn bạn thấy cung cấp cho hiệu suất Haskell tiệm cận với hiệu suất của C được viết theo kiểu đơn ngữ "cấp thấp" mà hầu hết các lập trình viên Haskell không thể viết. Ví dụ, bạn có thể đạt được hiệu suất tương tự bằng cách tạo mã Haskell đầu ra và biên dịch mã C. Vô nghĩa. Một vấn đề thực tế liên quan là những gì "bạn có thể làm" và những gì "có thể / có thể làm được". Nếu điều gì đó quá khó, nó không thực sự quan trọng nếu nó có thể trên lý thuyết (và "có thể" cho ai?).
Luigi Plinge

4

Ngôn ngữ chức năng tốt trong nhiều tình huống. Nó phụ thuộc vào các thư viện của một ngôn ngữ chức năng cụ thể.

Bạn sẽ trả lời câu hỏi "Khi nào thì sử dụng ngôn ngữ lập trình hướng đối tượng?"?


1
"Khi nào sử dụng ngôn ngữ lập trình hướng đối tượng?" Khi bạn muốn lập mô hình tính toán bất cứ thứ gì, mặt khác, tôi đang tìm kiếm một vấn đề mà fp sẽ là câu trả lời trực quan, tôi vẫn đang tìm, đó là cách tôi tìm thấy bài đăng này.
jimjim

@Arjang Tôi đoán lập trình chức năng sẽ tìm thấy công dụng to lớn trong các ứng dụng tính toán chỉ cần đầu vào để tạo đầu ra. Không mutability và không lặp
EdgeDev

3

Mặc dù đây là một câu hỏi khá chủ quan, tôi chỉ muốn nói thêm rằng các ngôn ngữ chức năng được sử dụng rất nhiều để phân tích cú pháp các ngôn ngữ miền cụ thể ; bản chất chức năng có lợi cho việc phân tích ngữ pháp.


2
Phân tích cú pháp DSL? Tôi nghĩ với macro Lisp và những thứ tương tự, DSL được triển khai dưới dạng macro, không phải thứ được phân tích cú pháp bởi các chương trình Lisp. YMMV với các ngôn ngữ không phải Lisp. :-P
Chris Jester-Young

1

Từ những gì tôi đã thấy, đó là vấn đề về hương vị hơn là chức năng (không có ý định chơi chữ). Thực sự không có bất cứ điều gì về một trong hai phong cách ngôn ngữ khiến nó vốn dĩ tốt hơn hoặc tệ hơn ở các nhiệm vụ cụ thể.


2
@JonHarrop - Bạn có quan tâm đến việc đó không? Tôi không thấy điều đó quá rõ ràng, và sẽ thật tiếc nếu bạn để lại ấn tượng rằng bạn đang bỏ phiếu cho mọi người khỏi sự phấn khích của tôi.
TED

1
Họ ML của ngôn ngữ được lai tạo đặc biệt để lập trình ẩn với việc bổ sung các tính năng ngôn ngữ phức tạp như khớp mẫu để thao tác cây (ví dụ cây biểu thức). Do đó, nhóm ngôn ngữ này vốn đã tốt hơn rất nhiều trong nhiệm vụ cụ thể đó.
JD

1
@JonHarrop - Tôi sẽ chấp nhận điều đó. Tuy nhiên, bạn đang nói về ML, không phải ngôn ngữ chức năng nói chung. Tôi là một người rất tin tưởng vào DSL vì vậy tôi chắc chắn sẽ không phản đối việc sử dụng một ngôn ngữ cụ thể cho nhiệm vụ chính xác mà nó được thiết kế.
TED

Ngày nay, so khớp mẫu được tìm thấy trong hầu hết các ngôn ngữ chức năng bao gồm OCaml, F #, Scala, Haskell, Clojure và Erlang. Ví dụ, gần đây tôi đã xây dựng một công cụ quy tắc kinh doanh riêng cho một khách hàng tập trung vào toán học. Đó là 1.000 dòng F # và chủ yếu là một thông dịch viên. Lexing, phân tích cú pháp, kiểm tra kiểu và thông dịch đầu vào đều dễ dàng hơn nhiều nhờ khớp mẫu.
JD

@JonHarrop .. nhưng không phải tất cả. Nó không phải là một tính năng cố hữu của các ngôn ngữ chức năng, đó là điều mà câu hỏi đặt ra.
TED

1

Nói chung, hãy sử dụng ngôn ngữ dễ dàng nhất để diễn đạt giải pháp cho một vấn đề. Đối với lập trình chức năng, đây là khi giải pháp cho một vấn đề dễ dàng được thể hiện dưới dạng các chức năng , do đó có tên. Nói chung nó tốt cho các phép toán, AI, khớp mẫu; nói chung là bất cứ điều gì có thể được chia nhỏ thành một tập hợp các quy tắc phải được áp dụng để có câu trả lời. Bạn chỉ có thể thực sự xác định ngôn ngữ "tốt nhất" để sử dụng sau khi bạn đã phân tích đầy đủ vấn đề của mình. Đây là lúc mã giả có ích. Nếu bạn thấy mình đang viết mã giả trông giống như FP, hãy sử dụng FP.

Tất nhiên, tất cả các ngôn ngữ lập trình hoàn chỉnh đều tương đương về mặt chức năng, vì vậy việc bạn chọn ngôn ngữ lập trình nào thực sự không quan trọng về vấn đề bạn có thể giải quyết. Các tác động chính sẽ là về hiệu quả và độ chính xác của mã hóa, và dễ bảo trì.

Cũng lưu ý rằng có thể bắt chước FP trong các ngôn ngữ OO thông qua các API được thiết kế thông minh. Ví dụ, tôi đã thấy nhiều thư viện Java (JMock là một ví dụ) sử dụng chuỗi phương thức để mô phỏng một FP DSL. Sau đó, bạn sẽ thấy các cấu trúc như:

logger.expects(once()).method("error") .with( and(stringContains(action),stringContains(cause)) );

Về cơ bản, điều này xây dựng một chức năng được đánh giá để xác định xem một số chuỗi gọi trên một đối tượng giả có đúng hay không. (ví dụ bị đánh cắp từ http://www.jmock.org/yoga.html )

Một cú pháp giống FP khác trong các ngôn ngữ OO khác là việc sử dụng các bao đóng, chẳng hạn như trong Ruby.


2
"... nó không thực sự quan trọng bạn chọn cái nào về những vấn đề bạn có thể giải quyết". Chỉ khi bạn có vô hạn thời gian và tiền bạc để giải quyết vấn đề của mình.
JD
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.