Lập trình khai báo là gì? [đóng cửa]


193

Tôi liên tục nghe thấy thuật ngữ này được đưa ra trong một số bối cảnh khác nhau. Nó là gì?


7
Câu trả lời bạn đã chọn là câu trả lời đúng (được biểu thị bằng dấu kiểm màu xanh lục), không chính xác. Nó không định nghĩa cái gì phân biệt lập trình khai báo với phản đề của nó-- lập trình mệnh lệnh. Hãy xem xét thay đổi lựa chọn của bạn.
Shelby Moore III

3
Có, câu trả lời được đánh dấu là đúng là KHÔNG đúng.
Dermot

4
@ShelbyMooreIII Cũng xác định câu trả lời nào là đúng để chúng ta có thể đọc nó!
vivek.m

@ vivek.m Tôi đã cung cấp một câu trả lời mới ngày hôm nay.
Shelby Moore III

Câu trả lời:


148

Lập trình khai báo là khi bạn viết mã của mình theo cách nó mô tả những gì bạn muốn làm, chứ không phải cách bạn muốn làm nó. Nó được để lại cho trình biên dịch để tìm ra làm thế nào.

Ví dụ về ngôn ngữ lập trình khai báo là SQL và Prolog.


29
Bạn vẫn phải tìm ra "cách" để nói với máy tính "những gì" bạn muốn :)
hasen

7
@hasenj câu trả lời này và các câu trả lời khác không xác định thuộc tính duy nhất không được chia sẻ với lập trình mệnh lệnh - đó là tính bất biến .
Shelby Moore III

3
Sẽ thực sự tuyệt vời nếu bạn có thể đề cập đến việc nó khác với lập trình bắt buộc như thế nào (các ngôn ngữ như C, C ++, C #) thì người đọc sẽ dễ dàng tạo ra sự khác biệt hơn.
RBT

1
lập trình viên : "Tôi muốn đi du lịch đến Paris." khai báo (c) : "Bạn muốn đến đó bằng cách nào? đi thuyền bằng thuyền? lập trình viên : "Tôi không có hứng thú với cách nó được thực hiện." mệnh lệnh (sql) : "Đừng lo lắng. Tôi có thể truy vấn những gì bạn cần." ( đây là cách tôi hiểu câu trả lời )
nate

Làm thế nào SQL có thể được khai báo nếu nó hỗ trợ các biểu thức không minh bạch tham chiếu?
java-nghiện602

80

Các câu trả lời khác đã làm một công việc tuyệt vời giải thích lập trình khai báo là gì, vì vậy tôi sẽ chỉ cung cấp một số ví dụ về lý do tại sao điều đó có thể hữu ích.

Bối cảnh độc lập

Chương trình khai báo là độc lập với bối cảnh . Bởi vì họ chỉ tuyên bố mục tiêu cuối cùng là gì, nhưng không phải là các bước trung gian để đạt được mục tiêu đó, cùng một chương trình có thể được sử dụng trong các bối cảnh khác nhau. Điều này khó thực hiện với các chương trình bắt buộc , bởi vì chúng thường phụ thuộc vào bối cảnh (ví dụ như trạng thái ẩn).

Lấy yaccmột ví dụ. Đó là một trình tạo phân tích cú pháp aka. trình biên dịch trình biên dịch, DSL khai báo bên ngoài để mô tả ngữ pháp của ngôn ngữ, để trình phân tích cú pháp cho ngôn ngữ đó có thể được tạo tự động từ mô tả. Do tính độc lập trong bối cảnh của nó, bạn có thể thực hiện nhiều điều khác nhau với ngữ pháp như vậy:

  • Tạo trình phân tích cú pháp C cho ngữ pháp đó (trường hợp sử dụng ban đầu cho yacc)
  • Tạo trình phân tích cú pháp C ++ cho ngữ pháp đó
  • Tạo trình phân tích cú pháp Java cho ngữ pháp đó (sử dụng Jay)
  • Tạo trình phân tích cú pháp C # cho ngữ pháp đó (sử dụng GPPG)
  • Tạo trình phân tích cú pháp Ruby cho ngữ pháp đó (sử dụng Racc)
  • Tạo trực quan hóa cây cho ngữ pháp đó (sử dụng GraphViz)
  • chỉ cần thực hiện một số cách in đẹp, định dạng ưa thích và tô sáng cú pháp của chính tệp nguồn yacc và đưa nó vào Tài liệu tham khảo của bạn như một đặc tả cú pháp của ngôn ngữ của bạn

Và nhiều thứ khác nữa …

Tối ưu hóa

Vì bạn không quy định máy tính sẽ thực hiện các bước nào và theo thứ tự nào, nó có thể sắp xếp lại chương trình của bạn một cách tự do hơn nhiều, thậm chí có thể thực hiện song song một số tác vụ. Một ví dụ điển hình là trình lập kế hoạch truy vấn và trình tối ưu hóa truy vấn cho cơ sở dữ liệu SQL. Hầu hết các cơ sở dữ liệu SQL cho phép bạn hiển thị truy vấn mà chúng thực sự đang thực thi so với truy vấn mà bạn yêu cầu chúng thực hiện. Thông thường, những truy vấn đó trông không có gìthích nhau Trình lập kế hoạch truy vấn đưa mọi thứ vào tài khoản mà bạn thậm chí không mơ tới: độ trễ quay của đĩa, ví dụ hoặc thực tế là một ứng dụng hoàn toàn khác cho một người dùng hoàn toàn khác chỉ thực hiện một truy vấn tương tự và bảng mà bạn đang có tham gia cùng và bạn đã làm việc rất chăm chỉ để tránh tải đã có trong bộ nhớ.

Có một trade-off thú vị ở đây: máy phải làm việc chăm chỉ hơn để tìm ra cách để làm điều gì đó hơn nó sẽ bằng một ngôn ngữ bắt buộc, nhưng khi nó làm con số nó ra, nó có tự do nhiều hơn và nhiều hơn nữa thông tin cho việc tối ưu hóa sân khấu.


23

Nhẹ nhàng:

Lập trình khai báo có xu hướng:

  • Các bộ khai báo, hoặc các câu lệnh khai báo, mỗi câu có ý nghĩa (thường trong miền vấn đề) và có thể được hiểu độc lập và tách biệt.

Lập trình mệnh lệnh có xu hướng:

  • Chuỗi các lệnh, mỗi lệnh thực hiện một số hành động; nhưng có thể có hoặc không có ý nghĩa trong miền vấn đề.

Kết quả là, một phong cách bắt buộc giúp người đọc hiểu được các cơ chế của những gì hệ thống đang thực sự làm, nhưng có thể đưa ra cái nhìn sâu sắc về vấn đề mà nó dự định sẽ giải quyết. Mặt khác, một phong cách khai báo giúp người đọc hiểu được miền vấn đề và cách tiếp cận mà hệ thống đưa ra để giải quyết vấn đề, nhưng ít thông tin hơn về vấn đề cơ học.

Các chương trình thực (ngay cả những chương trình được viết bằng các ngôn ngữ có lợi cho các đầu phổ, như ProLog hoặc C) có xu hướng có cả hai kiểu trình bày ở nhiều mức độ khác nhau ở các điểm khác nhau, để đáp ứng sự phức tạp và nhu cầu giao tiếp khác nhau của tác phẩm. Một phong cách không vượt trội so với phong cách khác; họ chỉ phục vụ các mục đích khác nhau, và, như với nhiều thứ trong cuộc sống, điều độ là chìa khóa.


Đó là câu trả lời đúng. Không phải bất kỳ điều gì lẩm bẩm ở trên
Krzysztof Wende

Cảm ơn bạn không chỉ trả lời câu hỏi mà còn thực hiện theo kiểu "Giải thích như tôi 5" với bối cảnh và thực tiễn. Câu trả lời tuyệt vời.
monsto

17

Đây là một ví dụ.

Trong CSS (được sử dụng để tạo kiểu trang HTML), nếu bạn muốn một yếu tố hình ảnh cao 100 pixel và rộng 100 pixel, bạn chỉ cần "khai báo" đó là những gì bạn muốn như sau:

#myImageId {
height: 100px;
width: 100px;
}

Bạn có thể coi CSS là ngôn ngữ "biểu định kiểu" khai báo.

Công cụ trình duyệt đọc và giải thích CSS này là miễn phí để làm cho hình ảnh trông cao và rộng như vậy theo ý muốn. Các công cụ trình duyệt khác nhau (ví dụ: công cụ cho IE, công cụ cho Chrome) sẽ thực hiện nhiệm vụ này khác nhau.

Tất nhiên, các triển khai duy nhất của họ KHÔNG được viết bằng ngôn ngữ khai báo mà bằng ngôn ngữ thủ tục như hội, C, C ++, Java, JavaScript hoặc Python. Mã đó là một loạt các bước được thực hiện từng bước (và có thể bao gồm các lệnh gọi hàm). Nó có thể thực hiện những việc như nội suy các giá trị pixel và hiển thị trên màn hình.


11

Tôi xin lỗi, nhưng tôi phải không đồng ý với nhiều câu trả lời khác. Tôi muốn ngăn chặn sự hiểu lầm nhầm lẫn này về định nghĩa của lập trình khai báo.

Định nghĩa

Độ trong suốt tham chiếu (RT) của các biểu thức con là thuộc tính bắt buộc duy nhất của biểu thức lập trình khai báo , vì đây là thuộc tính duy nhất không được chia sẻ với lập trình mệnh lệnh.

Các thuộc tính được trích dẫn khác của lập trình khai báo, xuất phát từ RT này. Vui lòng nhấp vào siêu liên kết ở trên để được giải thích chi tiết.

Ví dụ bảng tính

Hai câu trả lời đề cập đến lập trình bảng tính. Trong trường hợp lập trình bảng tính (còn gọi là công thức) không truy cập trạng thái toàn cầu có thể thay đổi , thì đó là lập trình khai báo. Điều này là do các giá trị ô có thể thay đổi là đầu vàođầu ra nguyên khối của main()(toàn bộ chương trình). Các giá trị mới không được ghi vào các ô sau khi mỗi công thức được thực thi, do đó chúng không thể thay đổi trong vòng đời của chương trình khai báo (thực hiện tất cả các công thức trong bảng tính). Do đó, liên quan đến nhau, các công thức xem các ô có thể thay đổi này là bất biến. Một chức năng RT được phép truy cập trạng thái toàn cầu bất biến (và cả trạng thái cục bộ có thể thay đổi ).

Do đó, khả năng biến đổi các giá trị trong các ô khi chương trình kết thúc (như một đầu ra từ main()), không làm cho chúng có thể thay đổi các giá trị được lưu trữ trong ngữ cảnh của các quy tắc. Điểm khác biệt chính là các giá trị ô không được cập nhật sau khi mỗi công thức bảng tính được thực hiện, do đó thứ tự thực hiện các công thức không quan trọng. Các giá trị ô được cập nhật sau khi tất cả các công thức khai báo đã được thực hiện.


1
Tác dụng phụ ngoài ý muốn có thể phá hủy mối quan hệ giữa những gì đã được tuyên bố và hành vi thực tế của chương trình. Tôi đã giải thích điều này chi tiết hơn trong một câu trả lời mới .
Shelby Moore III

8

Lập trình khai báo là bức tranh, trong đó lập trình mệnh lệnh là hướng dẫn để vẽ bức tranh đó.

Bạn đang viết theo kiểu khai báo nếu bạn "Kể nó là gì", thay vì mô tả các bước mà máy tính sẽ thực hiện để đến nơi bạn muốn.

Khi bạn sử dụng XML để đánh dấu dữ liệu, bạn đang sử dụng lập trình khai báo vì bạn đang nói "Đây là một người, đó là ngày sinh nhật và ở đó có một địa chỉ đường phố".

Một số ví dụ về nơi kết hợp lập trình khai báo và mệnh lệnh để có hiệu quả cao hơn:

  • Windows Presentation Foundation sử dụng cú pháp XML khai báo để mô tả giao diện người dùng trông như thế nào và các mối quan hệ (liên kết) là gì giữa các điều khiển và cấu trúc dữ liệu cơ bản.

  • Các tệp cấu hình có cấu trúc sử dụng cú pháp khai báo (đơn giản như các cặp "key = value") để xác định chuỗi hoặc giá trị của dữ liệu nghĩa là gì.

  • HTML đánh dấu văn bản bằng các thẻ mô tả vai trò của từng đoạn văn bản liên quan đến toàn bộ tài liệu.


2
Mặc dù XML là khai báo, tôi sẽ không đi xa để nói rằng đó là lập trình khai báo đơn giản vì không có ngữ nghĩa hoạt động liên quan đến đánh dấu. Nói rằng một cái gì đó là một địa chỉ không giúp tìm ra những gì bạn muốn làm với nó.
HenryR

1
Phải có một bối cảnh cơ bản (tên miền?) Trong đó chương trình khai báo được sử dụng. Vì vậy, sử dụng XML kết hợp với ANT có thể được hiểu là một chương trình khai báo.
Gutzofter

7

Lập trình khai báo là lập trình với các khai báo, tức là các câu khai báo. Câu khai báo có một số tính chất phân biệt chúng với câu mệnh lệnh. Cụ thể, khai báo là:

  • giao hoán (có thể được sắp xếp lại)
  • liên kết (có thể được tập hợp lại)
  • idempotent (có thể lặp lại mà không thay đổi về ý nghĩa)
  • đơn điệu (khai báo không trừ thông tin)

Một điểm liên quan là đây là tất cả các thuộc tính cấu trúc và trực giao với chủ đề. Tuyên bố không phải là về "Cái gì so với thế nào" . Chúng ta có thể khai báo (đại diện và ràng buộc) một "cách" dễ dàng như chúng ta khai báo "cái gì" . Tuyên bố là về cấu trúc, không phải nội dung. Lập trình khai báo có tác động đáng kể đến cách chúng ta trừu tượng hóa và cấu trúc lại mã của chúng ta và cách chúng ta mô đun hóa nó thành các chương trình con, nhưng không quá nhiều trên mô hình miền.

Thông thường, chúng ta có thể chuyển đổi từ mệnh lệnh sang khai báo bằng cách thêm ngữ cảnh. Ví dụ: từ "Rẽ trái. (... Đợi nó ...) Rẽ phải." thành "Bob sẽ rẽ trái tại ngã tư Foo và Bar lúc 11:01. Bob sẽ rẽ phải ở ngã tư Bar và Baz lúc 11:06." Lưu ý rằng trong trường hợp sau, các câu là bình thường và giao hoán, trong khi đó trong trường hợp trước, việc sắp xếp lại hoặc lặp lại các câu sẽ làm thay đổi nghiêm trọng ý nghĩa của chương trình.

Về đơn điệu , khai báo có thể thêm các ràng buộc trừ đi các khả năng . Nhưng các ràng buộc vẫn thêm thông tin (chính xác hơn, các ràng buộc là thông tin). Nếu chúng ta cần các khai báo thay đổi theo thời gian, thì điển hình là mô hình hóa điều này với ngữ nghĩa thời gian rõ ràng - ví dụ từ "quả bóng phẳng" đến "quả bóng phẳng tại thời điểm T". Nếu chúng ta có hai khai báo mâu thuẫn, chúng ta có một hệ thống khai báo không nhất quán, mặc dù điều này có thể được giải quyết bằng cách đưa ra các ràng buộc mềm (ưu tiên, xác suất, v.v.) hoặc sử dụng logic tương đương.


1
Biểu thức khai báo đóng góp vào hành vi dự định của chương trình, mệnh lệnh có thể đóng góp cho dự định hoặc ngoài ý muốn. Tuyên bố không cần phải giao hoán và bình thường, nếu đây là ngữ nghĩa có chủ ý.
Shelby Moore III

6

Mô tả cho máy tính những gì bạn muốn, không phải làm thế nào để làm một cái gì đó.


6

hãy tưởng tượng một trang excel. Với các cột được điền với các công thức để tính toán khai thuế của bạn.

Tất cả logic được thực hiện khai báo trong các ô, thứ tự tính toán được xác định bằng chính công thức chứ không phải theo thủ tục.

Đó là loại những gì lập trình khai báo là tất cả về. Bạn khai báo không gian vấn đề và giải pháp thay vì luồng của chương trình.

Prolog là ngôn ngữ khai báo duy nhất tôi sử dụng. Nó đòi hỏi một kiểu suy nghĩ khác nhưng thật tốt khi học nếu chỉ đưa bạn đến một thứ khác ngoài ngôn ngữ lập trình thủ tục thông thường.


6

Tôi đã tinh chỉnh hiểu biết của tôi về lập trình khai báo, kể từ tháng 12 năm 2011 khi tôi cung cấp câu trả lời cho câu hỏi này. Dưới đây theo sự hiểu biết hiện tại của tôi.

Phiên bản dài của sự hiểu biết của tôi (nghiên cứu) được trình bày chi tiết tại liên kết này , bạn nên đọc để có được sự hiểu biết sâu sắc về bản tóm tắt tôi sẽ cung cấp dưới đây.

Lập trình mệnh lệnh là nơi lưu trữ và đọc trạng thái có thể thay đổi, do đó, việc sắp xếp và / hoặc sao chép các hướng dẫn chương trình có thể thay đổi hành vi (ngữ nghĩa) của chương trình (và thậm chí gây ra lỗi, tức là hành vi ngoài ý muốn).

Theo nghĩa ngây thơ và cực đoan nhất (mà tôi đã khẳng định trong câu trả lời trước của mình), lập trình khai báo (DP) đang tránh tất cả trạng thái có thể thay đổi được lưu trữ, do đó, việc đặt hàng và / hoặc sao chép các hướng dẫn chương trình KHÔNG thể thay đổi hành vi (ngữ nghĩa) của chương trình .

Tuy nhiên, một định nghĩa cực đoan như vậy sẽ không hữu ích lắm trong thế giới thực, vì gần như mọi chương trình đều liên quan đến trạng thái có thể thay đổi được lưu trữ. Các bảng tính ví dụ chiếu theo định nghĩa cực đoan này của DP, bởi vì toàn bộ mã chương trình được chạy để hoàn thành với một bản tĩnh của nhà nước đầu vào, trước khi các quốc gia mới được lưu trữ. Sau đó, nếu bất kỳ trạng thái được thay đổi, điều này được lặp lại. Nhưng hầu hết các chương trình trong thế giới thực không thể bị giới hạn trong một mô hình nguyên khối về những thay đổi trạng thái.

Một định nghĩa hữu ích hơn về DP là việc đặt hàng và / hoặc sao chép các hướng dẫn lập trình không làm thay đổi bất kỳ ngữ nghĩa mờ nào. Nói cách khác, không có thay đổi ngẫu nhiên ẩn trong ngữ nghĩa xảy ra-- mọi thay đổi trong thứ tự hướng dẫn chương trình và / hoặc trùng lặp chỉ gây ra những thay đổi có chủ đích và minh bạch đối với hành vi của chương trình.

Bước tiếp theo sẽ là nói về mô hình lập trình hoặc mô hình hỗ trợ nào trong DP, nhưng đó không phải là câu hỏi ở đây.


Cập nhật: vui lòng tham khảo phần giải thích thấu đáo hơn ở câu trả lời khác của tôi về định nghĩa lập trình khai báo.
Shelby Moore III

Functional programminglà một từ buzz ngày nay mà về cơ bản là một tập hợp con của lập trình khai báo. LINQ trong ngôn ngữ C # là một yếu tố của lập trình chức năng khi bản chất ngôn ngữ là bắt buộc. Vì vậy, C # trở thành loại lai theo định nghĩa đó.
RBT

1
Liên kết compute.com đã chết.
Kedar Mhaswade

5

Đó là một phương pháp lập trình dựa trên việc mô tả những gì nên làm hoặc thay vì mô tả cách thức hoạt động của nó.

Nói cách khác, bạn không viết các thuật toán được tạo thành từ các biểu thức, bạn chỉ cần bố trí cách bạn muốn mọi thứ trở thành. Hai ví dụ điển hình là HTML và WPF.

Bài viết Wikipedia này là một tổng quan tốt: http://en.wikipedia.org/wiki/Declarative_programming


1
Nhỏ ngụy biện. WPF là một thư viện, không thực sự là một ngôn ngữ hay một mô hình. Tôi nghĩ bạn thực sự muốn nói XAML là một ví dụ về ngôn ngữ khai báo.
Nick

Và làm thế nào bạn sẽ mô tả lập trình bằng thư viện / khung?
Gutzofter

Không đúng khi tuyên bố rằng lập trình khai báo không thể chứa các biểu thức. Điểm khác biệt chính là các biểu thức không thể thay đổi các giá trị được lưu trữ .
Shelby Moore III

HTML không phải là một ngôn ngữ lập trình
Lud

5

Vì tôi đã viết câu trả lời trước của mình, tôi đã đưa ra một định nghĩa mới về tài sản khai báo được trích dẫn dưới đây. Tôi cũng đã định nghĩa lập trình mệnh lệnh là thuộc tính kép.

Định nghĩa này là tốt hơn so với câu tôi đã cung cấp trong câu trả lời trước của tôi, bởi vì nó ngắn gọn và nó khái quát hơn. Nhưng nó có thể khó khăn hơn để mò mẫm, bởi vì hàm ý của các định lý không hoàn chỉnh áp dụng cho lập trình và cuộc sống nói chung rất khó để con người quấn lấy tâm trí của họ.

Các giải thích được trích dẫn của định nghĩa thảo luận về vai trò của lập trình chức năng thuần túy trong lập trình khai báo.

Tuyên bố so với mệnh lệnh

Thuộc tính khai báo là kỳ lạ, khó hiểu và khó nắm bắt trong một định nghĩa chính xác về mặt kỹ thuật vẫn còn chung chung và không mơ hồ, bởi vì đó là một khái niệm ngây thơ rằng chúng ta có thể tuyên bố ý nghĩa (còn gọi là ngữ nghĩa) của chương trình mà không phát sinh tác dụng phụ ngoài ý muốn. Có một sự căng thẳng cố hữu giữa việc thể hiện ý nghĩa và tránh các tác động ngoài ý muốn, và sự căng thẳng này thực sự xuất phát từ các định lý không hoàn chỉnh của lập trình và vũ trụ của chúng ta.

Đó là sự đơn giản hóa, về mặt kỹ thuật không chính xác, và thường không rõ ràng để xác định tường thuật như phải làm gì và bắt buộc như làm thế nào để làm . Một trường hợp nhập nhằng là “ những gì là” the “ như thế nào ” trong một chương trình mà kết quả đầu ra một theo chương trình một trình biên dịch.

Rõ ràng là đệ quy không giới hạn làm cho một ngôn ngữ Turing hoàn chỉnh , cũng tương tự trong ngữ nghĩa, không chỉ trong cấu trúc cú pháp đánh giá (còn gọi là ngữ nghĩa hoạt động). Đây là một ví dụ về mặt logic tương tự như định lý của Gôdel, bất kỳ hệ thống tiên đề hoàn chỉnh nào cũng không nhất quán . Suy ngẫm về sự kỳ lạ mâu thuẫn của trích dẫn đó! Nó cũng là một ví dụ chứng minh làm thế nào biểu thức ngữ nghĩa không có ràng buộc có thể chứng minh được, do đó chúng ta không thể chứng minh 2 rằng một chương trình (và tương tự như ngữ nghĩa của nó) dừng lại là định lý Dừng.

Các định lý không hoàn chỉnh xuất phát từ bản chất cơ bản của vũ trụ của chúng ta, như đã nêu trong Định luật Nhiệt động lực học thứ hai là entropy (hay còn gọi là # khả năng độc lập) đang có xu hướng tối đa mãi mãi . Việc mã hóa và thiết kế chương trình không bao giờ kết thúc được. Nó còn sống! - bởi vì nó cố gắng giải quyết nhu cầu của thế giới thực, và ngữ nghĩa của thế giới thực luôn thay đổi và có xu hướng nhiều khả năng hơn. Con người không bao giờ ngừng khám phá những điều mới (bao gồm cả lỗi trong các chương trình ;-).

Để nắm bắt chính xác và kỹ thuật khái niệm mong muốn đã nói ở trên trong vũ trụ kỳ lạ không có lợi thế này (hãy suy nghĩ rằng! Không có câu hỏi nào bên ngoài vũ trụ của chúng ta), đòi hỏi một định nghĩa ngắn gọn nhưng không đơn giản sẽ nghe không chính xác cho đến khi nó được giải thích sâu sắc.

Định nghĩa:


Thuộc tính khai báo là nơi chỉ có thể tồn tại một tập hợp các câu lệnh có thể biểu thị từng ngữ nghĩa mô-đun cụ thể.

Thuộc tính mệnh lệnh 3 là thuộc tính kép, trong đó ngữ nghĩa không nhất quán theo thành phần và / hoặc có thể được thể hiện bằng các biến thể của các bộ câu lệnh.


Định nghĩa khai báo này đặc biệt cục bộ trong phạm vi ngữ nghĩa, có nghĩa là nó yêu cầu một ngữ nghĩa mô-đun duy trì ý nghĩa nhất quán của nó bất kể nó được khởi tạo và sử dụng trong phạm vi toàn cầu ở đâu và như thế nào . Do đó, mỗi ngữ nghĩa mô-đun khai báo phải trực giao với tất cả những người khác có thể khác và không phải là một thuật toán toàn cầu (do các định lý không hoàn hảo) để chứng kiến ​​tính nhất quán, cũng là điểm của Thay vì không phải lúc nào cũng tốt hơn bởi Robert Harper, Giáo sư Khoa học máy tính tại Đại học Carnegie Mellon, một trong những nhà thiết kế của Standard ML.

Ví dụ về các ngữ nghĩa tường thuật mô-đun bao gồm loại functors lý thuyết, ví dụ như cácApplicative , gõ danh nghĩa, không gian tên, tên trường này, và wrt để cấp độ hoạt động của ngữ nghĩa sau đó lập trình chức năng thuần túy.

Do đó, các ngôn ngữ khai báo được thiết kế tốt có thể diễn đạt rõ ràng hơn ý nghĩa , mặc dù có một số mất tính tổng quát trong những gì có thể diễn đạt, nhưng đạt được những gì có thể được thể hiện với tính nhất quán nội tại.

Một ví dụ về định nghĩa đã nói ở trên là tập hợp các công thức trong các ô của chương trình bảng tính mà không mong đợi sẽ có cùng ý nghĩa khi được chuyển đến các ô cột và hàng khác nhau, tức là các định danh ô đã thay đổi. Các định danh ô là một phần và không thừa đối với ý nghĩa dự định. Vì vậy, mỗi kết quả bảng tính là wrt duy nhất cho các định danh ô trong một tập hợp các công thức. Ngữ nghĩa mô đun nhất quán trong trường hợp này là sử dụng các định danh ô làm đầu vào và đầu ra của các hàm thuần cho các công thức ô (xem bên dưới).

Ngôn ngữ đánh dấu siêu văn bản hay còn gọi là HTML. Ngôn ngữ cho các trang web tĩnh là một ví dụ về ngôn ngữ khai báo cao (nhưng không hoàn hảo 3 ) mà (ít nhất là trước HTML 5) không có khả năng diễn đạt hành vi động. HTML có lẽ là ngôn ngữ dễ học nhất. Đối với hành vi động, một ngôn ngữ kịch bản bắt buộc như JavaScript thường được kết hợp với HTML. HTML không có JavaScript phù hợp với định nghĩa khai báo vì mỗi loại danh nghĩa (nghĩa là các thẻ) duy trì ý nghĩa nhất quán của nó theo thành phần trong các quy tắc của cú pháp.

Một định nghĩa cạnh tranh đối với khai báo là giao hoánidempotent tính chất của những điều khoản về ngữ nghĩa, tức là giấy chi tiết có thể được sắp xếp lại và lặp lại mà không thay đổi ý nghĩa. Ví dụ: các câu lệnh gán giá trị cho các trường được đặt tên có thể được sắp xếp lại và sao chép mà không thay đổi ý nghĩa của chương trình, nếu các tên đó được mô đun hóa theo bất kỳ thứ tự ngụ ý nào. Các tên đôi khi ngụ ý một đơn đặt hàng, ví dụ như số nhận dạng ô bao gồm vị trí cột và hàng của chúng, việc di chuyển tổng số trên bảng tính sẽ thay đổi ý nghĩa của nó. Mặt khác, các thuộc tính này hoàn toàn yêu cầu toàn cầutính nhất quán của ngữ nghĩa. Nhìn chung, không thể thiết kế ngữ nghĩa của các câu lệnh sao cho chúng vẫn nhất quán nếu được sắp xếp ngẫu nhiên hoặc trùng lặp, bởi vì thứ tự và trùng lặp là nội tại đối với ngữ nghĩa. Ví dụ, các câu lệnh Foo Foo tồn tại (và xây dựng) và Foo Foo không tồn tại (và phá hủy). Nếu người ta xem xét sự không nhất quán ngẫu nhiên về mặt hóa học của ngữ nghĩa dự định, thì người ta chấp nhận định nghĩa này là đủ chung cho thuộc tính khai báo. Về bản chất, định nghĩa này là không rõ ràng như một định nghĩa tổng quát vì nó cố gắng tạo sự nhất quán trực giao với ngữ nghĩa, nghĩa là thách thức thực tế rằng vũ trụ ngữ nghĩa là không bị ràng buộc và không thể bị bắt trong một mô hình kết hợp toàn cầu .

Yêu cầu các đặc tính giao hoán và không cần thiết cho (thứ tự đánh giá cấu trúc của) ngữ nghĩa hoạt động cấp thấp hơn chuyển đổi ngữ nghĩa hoạt động thành một ngữ nghĩa mô đun cục bộ khai báo , ví dụ lập trình hàm thuần túy (bao gồm cả đệ quy thay vì các vòng lặp bắt buộc). Sau đó, thứ tự hoạt động của các chi tiết thực hiện không ảnh hưởng (tức là lan rộng ra toàn cầu ) tính nhất quán của ngữ nghĩa cấp cao hơn. Ví dụ, thứ tự đánh giá (và về mặt lý thuyết cũng là sự trùng lặp) của các công thức bảng tính không thành vấn đề vì các đầu ra không được sao chép vào các đầu vào cho đến khi tất cả các đầu ra đã được tính toán, nghĩa là tương tự với các hàm thuần túy.

C, Java, C ++, C #, PHP và JavaScript không đặc biệt khai báo. Cú pháp của Copute và cú pháp của Python được kết hợp nhiều hơn với các kết quả dự định , nghĩa là ngữ nghĩa cú pháp nhất quán loại bỏ tính không liên quan để người ta có thể dễ dàng hiểu được mã sau khi họ quên nó. Copute và Haskell thi hành tính xác định của ngữ nghĩa hoạt động và khuyến khích Cameron không lặp lại chính mình (DRY), bởi vì chúng chỉ cho phép mô hình chức năng thuần túy.


2 Ngay cả khi chúng ta có thể chứng minh ngữ nghĩa của một chương trình, ví dụ với ngôn ngữ Coq, điều này bị giới hạn trong ngữ nghĩa được thể hiện trong cách gõ và việc gõ không bao giờ có thể nắm bắt tất cả các ngữ nghĩa của chương trình, ngay cả đối với các ngôn ngữ chưa hoàn thành Turing, ví dụ với HTML + CSS, có thể biểu thị các kết hợp không nhất quán do đó có ngữ nghĩa không xác định.

3 Nhiều giải thích không chính xác cho rằng chỉ có lập trình mệnh lệnh mới có các câu lệnh được tổng hợp. Tôi đã làm rõ sự nhầm lẫn này giữa lập trình mệnh lệnh và chức năng . Ví dụ, thứ tự của các câu lệnh HTML không làm giảm tính nhất quán về nghĩa của chúng.


Chỉnh sửa: Tôi đã đăng bình luận sau đây lên blog của Robert Harper:

trong lập trình chức năng ... phạm vi biến thể của một biến là một loại

Tùy thuộc vào cách người ta phân biệt chức năng với lập trình mệnh lệnh, 'khả năng được gán' của bạn trong một chương trình bắt buộc cũng có thể có một loại đặt ràng buộc vào tính biến thiên của nó.

Định nghĩa không bị nhầm lẫn duy nhất mà tôi hiện đánh giá cao cho lập trình chức năng là a) các hàm như các đối tượng và loại hạng nhất, b) ưu tiên cho đệ quy trên các vòng lặp và / hoặc c) các hàm thuần túy tức là các hàm đó không ảnh hưởng đến ngữ nghĩa mong muốn của chương trình khi được ghi nhớ ( do đó lập trình chức năng hoàn toàn thuần túy không tồn tại trong ngữ nghĩa biểu thị mục đích chung do tác động của ngữ nghĩa hoạt động, ví dụ phân bổ bộ nhớ ).

Thuộc tính idempotent của một hàm thuần có nghĩa là lệnh gọi hàm trên các biến của nó có thể được thay thế bằng giá trị của nó, thường không phải là trường hợp cho các đối số của một thủ tục bắt buộc. Các hàm thuần túy dường như là wrt khai báo cho các chuyển trạng thái không tách rời giữa các kiểu đầu vào và kết quả.

Nhưng thành phần của các hàm thuần túy không duy trì bất kỳ tính nhất quán nào như vậy, bởi vì có thể mô hình hóa một quy trình bắt buộc tác dụng phụ (trạng thái toàn cầu) bằng ngôn ngữ lập trình hàm thuần túy, ví dụ IOMonad của Haskell và hơn nữa, hoàn toàn không thể ngăn chặn việc đó bất kỳ Turing hoàn thành ngôn ngữ lập trình chức năng thuần túy.

Như tôi đã viết vào năm 2012 có vẻ như có sự đồng thuận tương tự của các bình luận trong blog gần đây của bạn , rằng lập trình khai báo là một nỗ lực để nắm bắt khái niệm rằng ngữ nghĩa dự định không bao giờ mờ đục. Ví dụ về ngữ nghĩa mờ là sự phụ thuộc vào thứ tự, sự phụ thuộc vào việc xóa ngữ nghĩa cấp cao hơn ở lớp ngữ nghĩa hoạt động (ví dụ: phôi không phải là chuyển đổi và tổng quát giới hạn ngữ nghĩa cấp cao hơn ) và không thể kiểm tra được các giá trị biến đổi đúng) bởi ngôn ngữ lập trình.

Vì vậy, tôi đã kết luận rằng chỉ những ngôn ngữ hoàn chỉnh không Turing mới có thể được khai báo.

Do đó, một thuộc tính rõ ràng và khác biệt của ngôn ngữ khai báo có thể là đầu ra của nó có thể được chứng minh là tuân theo một số quy tắc tổng quát. Ví dụ, đối với bất kỳ chương trình HTML cụ thể nào (bỏ qua sự khác biệt trong cách phân tích trình thông dịch) không được viết theo kịch bản (nghĩa là không hoàn thành Turing) thì có thể đếm được biến thiên đầu ra của nó. Hay ngắn gọn hơn, một chương trình HTML là một chức năng thuần túy của tính biến đổi của nó. Ditto một chương trình bảng tính là một hàm thuần túy của các biến đầu vào của nó.

Vì vậy, dường như đối với tôi, các ngôn ngữ khai báo là phản đề của đệ quy không giới hạn , nghĩa là các định lý không hoàn chỉnh thứ hai của Gôdel không thể được chứng minh.

Lesie Lamport đã viết một câu chuyện cổ tích về cách Euclid có thể đã làm việc xung quanh các định lý không hoàn chỉnh của Gôdel áp dụng cho các bằng chứng toán học trong bối cảnh ngôn ngữ lập trình bằng cách kết hợp giữa các loại và logic (tương ứng Curry-Howard, v.v.).


4

Lập trình khai báo là "hành động lập trình bằng các ngôn ngữ phù hợp với mô hình tinh thần của nhà phát triển hơn là mô hình hoạt động của máy".

Sự khác biệt giữa lập trình khai báo và mệnh lệnh được minh họa rõ bởi vấn đề phân tích dữ liệu có cấu trúc.

Một chương trình bắt buộc sẽ sử dụng các hàm đệ quy lẫn nhau để tiêu thụ đầu vào và tạo dữ liệu. Một chương trình khai báo sẽ diễn tả một ngữ pháp xác định cấu trúc của dữ liệu để sau đó nó có thể được phân tích cú pháp.

Sự khác biệt giữa hai cách tiếp cận này là chương trình khai báo tạo ra một ngôn ngữ mới được ánh xạ chặt chẽ hơn với mô hình tinh thần của vấn đề hơn là ngôn ngữ chủ của nó.


2

Nghe có vẻ lạ, nhưng tôi đã thêm Excel (hoặc bất kỳ bảng tính nào thực sự) vào danh sách các hệ thống khai báo. Một ví dụ tốt về điều này được đưa ra ở đây .


1

Tôi muốn giải thích nó vì DP là một cách để thể hiện

  • Một biểu thức mục tiêu , các điều kiện cho - những gì chúng tôi đang tìm kiếm. Có một, có thể hoặc nhiều?
  • Một số sự thật được biết đến
  • Các quy tắc mở rộng sự thật

... Và nơi có một công cụ khấu trừ thường làm việc với thuật toán hợp nhất để tìm các mục tiêu.


-1

Theo như tôi có thể nói, nó bắt đầu được sử dụng để mô tả các hệ thống lập trình như Prolog, bởi vì prolog là (được cho là) ​​về việc khai báo mọi thứ theo một cách trừu tượng.

Nó ngày càng có nghĩa là rất ít, vì nó có định nghĩa được đưa ra bởi người dùng ở trên. Cần phải rõ ràng rằng có một khoảng cách giữa lập trình khai báo của Haskell, so với lập trình khai báo của HTML.


1
Không có "khoảng cách giữa lập trình khai báo của Haskell, so với lập trình khai báo của HTML", bởi vì thuộc tính gốc của lập trình khai báo là tính bất biến của các giá trị được lưu trữ.
Shelby Moore III

Như thể có thể, có một sự khác biệt hợp lý giữa một ngôn ngữ dành riêng cho tên miền bị ràng buộc trong các tính toán ngầm của nó, so với một hệ thống lập trình hoàn chỉnh.
Marcin

Đã đồng ý. Turing-đầy đủ là trực giao với tính bất biến của các giá trị được lưu trữ. Vì vậy, chúng ta không nên kết hợp với thuộc tính khai báo và mệnh lệnh. Cảm ơn bạn đã suy nghĩ về một trong những thuộc tính (Turing-đầy đủ) có thể gây ra "vịnh" đó.
Shelby Moore III

Hoàn thành quay vòng chỉ yêu cầu đệ quy không giới hạn . Tính không thay đổi của các giá trị được lưu trữ không loại trừ đệ quy không giới hạn. Do đó chúng là thuộc tính trực giao.
Shelby Moore III

-2

Một vài ví dụ khác về lập trình khai báo:

  • Đánh dấu ASP.Net cho cơ sở dữ liệu. Nó chỉ nói "điền vào lưới này với nguồn này", ví dụ, và để nó cho hệ thống để biết điều đó xảy ra như thế nào.
  • Biểu thức Linq

Lập trình khai báo là tốt vì nó có thể giúp đơn giản hóa mô hình tinh thần * của bạn và bởi vì cuối cùng nó có thể mở rộng hơn.

Ví dụ: giả sử bạn có một hàm thực hiện điều gì đó cho từng phần tử trong một mảng hoặc danh sách. Mã truyền thống sẽ trông như thế này:

foreach (object item in MyList)
{
   DoSomething(item);
}

Không có vấn đề lớn ở đó. Nhưng điều gì sẽ xảy ra nếu bạn sử dụng cú pháp khai báo nhiều hơn và thay vào đó xác định DoS Something () là một Hành động? Sau đó, bạn có thể nói theo cách này:

MyList.ForEach(DoSometing);

Điều này, tất nhiên, ngắn gọn hơn. Nhưng tôi chắc chắn rằng bạn có nhiều mối quan tâm hơn là chỉ lưu hai dòng mã ở đây và đó. Hiệu suất, ví dụ. Cách cũ, xử lý phải được thực hiện theo trình tự. Điều gì sẽ xảy ra nếu phương thức .orEach () có cách để bạn báo hiệu rằng nó có thể xử lý song song việc xử lý song song? Bây giờ, thật bất ngờ, bạn đã tạo mã của mình đa luồng theo cách rất an toàn và chỉ thay đổi một dòng mã. Và trên thực tế, có một phần mở rộng cho .Net cho phép bạn làm điều đó.

  • Nếu bạn theo liên kết đó, nó sẽ đưa bạn đến một bài đăng trên blog của một người bạn của tôi. Toàn bộ bài viết hơi dài, nhưng bạn có thể cuộn xuống tiêu đề có tiêu đề "Vấn đề" _và chọn nó không có vấn đề gì. *


Lập trình khai báo có thể làm thay đổi các giá trị được lưu trữ ... chỉ là bạn chỉ định (khai báo) những gì bạn muốn thay đổi thay vì chính xác cách thực hiện chính xác về cách biến đổi nó. Bạn nghĩ gì khác về một câu lệnh INSERT hoặc UPDATE trong sql không?
Joel Coehoorn

Bạn đang thiếu điểm rằng nếu các chức năng của bạn không thuần túy, thì các tác dụng phụ ngoài ý muốn có thể phá hủy mối quan hệ giữa những gì bạn đã khai báo và hành vi thực tế của chương trình. Tôi đã giải thích điều này chi tiết hơn trong một câu trả lời mới .
Shelby Moore III

-3

Nó phụ thuộc vào cách bạn gửi câu trả lời cho văn bản. Nhìn chung, bạn có thể nhìn vào chương trình ở một góc nhìn nhất định nhưng nó phụ thuộc vào góc nhìn của bạn về vấn đề. Tôi sẽ giúp bạn bắt đầu với chương trình: Dim Bus, Ô tô, Thời gian, Chiều cao như Integr

Một lần nữa, nó phụ thuộc vào những gì vấn đề là một tổng thể. Bạn có thể phải rút ngắn nó do chương trình. Hy vọng điều này sẽ giúp và cần thông tin phản hồi nếu nó không. Cảm ơn bạn.

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.