Trên nhiều bài viết, mô tả lợi ích của lập trình chức năng, tôi đã thấy các ngôn ngữ lập trình chức năng, như Haskell, ML, Scala hoặc Clojure, được gọi là "ngôn ngữ khai báo" khác với các ngôn ngữ bắt buộc như C / C ++ / C # / Java. Câu hỏi của tôi là những gì làm cho ngôn ngữ lập trình chức năng khai báo trái ngược với mệnh lệnh.
Một lời giải thích thường gặp khi mô tả sự khác biệt giữa lập trình Tuyên bố và Bắt buộc là trong lập trình mệnh lệnh, bạn nói với máy tính "Cách làm một việc gì đó" trái ngược với "Phải làm gì" trong các ngôn ngữ khai báo. Vấn đề tôi có với lời giải thích này là bạn liên tục làm cả hai trong tất cả các ngôn ngữ lập trình. Ngay cả khi bạn đi xuống tổ hợp cấp thấp nhất, bạn vẫn nói với máy tính "Phải làm gì", bạn bảo CPU thêm hai số, bạn không hướng dẫn cách thực hiện phép cộng. Nếu chúng ta đi đến đầu kia của quang phổ, một ngôn ngữ chức năng thuần túy cấp cao như Haskell, thì thực tế bạn đang nói với máy tính cách đạt được một nhiệm vụ cụ thể, đó là những gì chương trình của bạn là một chuỗi các hướng dẫn để đạt được một nhiệm vụ cụ thể mà máy tính không biết làm thế nào để đạt được một mình. Tôi hiểu rằng các ngôn ngữ như Haskell, Clojure, v.v ... rõ ràng là cấp độ cao hơn C / C ++ / C # / Java và cung cấp các tính năng như đánh giá lười biếng, cấu trúc dữ liệu bất biến, chức năng ẩn danh, currying, cấu trúc dữ liệu liên tục, v.v. lập trình chức năng có thể và hiệu quả, nhưng tôi sẽ không phân loại chúng thành ngôn ngữ khai báo.
Một ngôn ngữ khai báo thuần túy đối với tôi sẽ là một ngôn ngữ chỉ bao gồm các khai báo, một ví dụ về các ngôn ngữ như vậy sẽ là CSS (Có tôi biết CSS về mặt kỹ thuật không phải là ngôn ngữ lập trình). CSS chỉ chứa các khai báo kiểu được sử dụng bởi HTML và Javascript của trang. CSS không thể làm gì khác ngoài việc khai báo, nó không thể tạo các hàm lớp, tức là các hàm xác định kiểu hiển thị dựa trên một số tham số, bạn không thể thực thi các tập lệnh CSS, v.v. Điều đó đối với tôi mô tả một ngôn ngữ khai báo (chú ý tôi không nói khai báo ngôn ngữ lập trình ).
Cập nhật:
Gần đây tôi đã chơi với Prolog và với tôi, Prolog là ngôn ngữ lập trình gần nhất với ngôn ngữ khai báo đầy đủ (Ít nhất là theo ý kiến của tôi), nếu đó không phải là ngôn ngữ lập trình khai báo đầy đủ duy nhất. Để xây dựng chương trình trong Prolog được thực hiện bằng cách khai báo trong đó nêu thực tế (một hàm vị ngữ trả về giá trị true cho một đầu vào cụ thể) hoặc một quy tắc (một hàm vị ngữ trả về true cho một điều kiện / mẫu đã cho dựa trên các đầu vào), các quy tắc được xác định bằng cách sử dụng một kỹ thuật khớp mẫu. Để làm bất cứ điều gì trong prolog, bạn truy vấn cơ sở tri thức bằng cách thay thế một hoặc nhiều đầu vào của một vị từ bằng một biến và prolog cố gắng tìm các giá trị cho (các) biến mà vị từ đó thành công.
Quan điểm của tôi là trong prolog không có hướng dẫn bắt buộc, về cơ bản bạn nói (khai báo) máy tính những gì nó biết và sau đó hỏi (truy vấn) về kiến thức. Trong các ngôn ngữ lập trình chức năng, bạn vẫn đưa ra các hướng dẫn, ví dụ như lấy một giá trị, gọi hàm X và thêm 1 vào nó, v.v., ngay cả khi bạn không trực tiếp thao tác các vị trí bộ nhớ hoặc viết ra từng bước tính toán. Tôi sẽ không nói rằng lập trình trong Haskell, ML, Scala hoặc Clojure là khai báo theo nghĩa này, mặc dù tôi có thể sai. Là đúng, đúng, khai báo lập trình chức năng thuần túy theo nghĩa mà tôi đã mô tả ở trên.
(let [x 1] (let [x (+ x 2)] (let [x (* x x)] x)))
(Hy vọng bạn hiểu điều đó, Clojure). Câu hỏi ban đầu của tôi là những gì làm cho điều này khác với int này x = 1; x += 2; x *= x; return x;
Theo tôi nó gần như giống nhau.