Những gì bạn chủ yếu hỏi về sự khác biệt giữa sức mạnh tính toán và cái thường được gọi là sức mạnh biểu cảm (hoặc chỉ là biểu cảm ) của một ngôn ngữ (hoặc hệ thống tính toán).
Khả năng tính toán
Sức mạnh tính toán đề cập đến những loại vấn đề mà ngôn ngữ có thể tính toán. Loại sức mạnh tính toán nổi tiếng nhất là tương đương với Máy Turing phổ dụng . Có rất nhiều hệ thống tính toán khác, chẳng hạn như Máy truy cập ngẫu nhiên , tính toán ,, tính toán tổ hợp SK , hàm đệ quy , WHILE
chương trình và nhiều hệ thống khác. Và hóa ra, tất cả những thứ này có thể mô phỏng lẫn nhau, điều đó có nghĩa là tất cả chúng đều có sức mạnh tính toán như nhau.
Điều này dẫn đến Luận án Turing Church (được đặt theo tên của Alonzo Church , người đã tạo ra calcul-tính toán và Alan Turing , người đã tạo ra Máy Turing phổ dụng). Luận án Giáo hội là một giả thuyết về khả năng tính toán với hai khía cạnh:
- tất cả các hệ thống máy tính có khả năng tính toán chung đều mạnh như nhau và
- một người theo thuật toán có thể tính toán chính xác các chức năng mà Máy Turing (và do đó, bất kỳ hệ thống nào khác) có thể tính toán.
Thứ hai là quan trọng trong lĩnh vực triết học của tâm trí hơn là khoa học máy tính.
Tuy nhiên, có hai điều mà Luận án Giáo hội không nói, rất phù hợp với câu hỏi của bạn:
- cách hiệu quả các mô phỏng khác nhau đang có và
- làm thế nào thuận tiện mã hóa của một vấn đề là.
Một ví dụ đơn giản cho (1): trên Máy truy cập ngẫu nhiên, sao chép một mảng sẽ mất thời gian tỷ lệ thuận với độ dài của mảng. Trên một máy Turing, tuy nhiên, phải mất thời gian tỉ lệ với bình phương của chiều dài của mảng, bởi vì máy Turing không có quyền truy cập bộ nhớ ngẫu nhiên, nó chỉ có thể di chuyển trên băng một tế bào cùng một lúc. Do đó, nó cần phải di chuyển qua n phần tử của mảng n lần để sao chép chúng. Vì vậy, các mô hình tính toán khác nhau có thể có các đặc tính hiệu suất khác nhau, ngay cả trong trường hợp tiệm cận, nơi chúng tôi cố gắng trừu tượng hóa khỏi các chi tiết thực hiện.
Ví dụ cho (2) rất nhiều: cả-tính toán và Python đều hoàn thành Turing. Nhưng bạn có muốn viết một chương trình bằng Python hoặc bằng calcul-tính toán không?
Ngoài ra còn có một nếp nhăn thứ ba mà tôi đã bỏ qua cho đến bây giờ: tất cả các hệ thống ban đầu đó được thiết kế bởi các nhà logic học, triết gia hoặc nhà toán học, không phải bởi các nhà khoa học máy tính, đơn giản là vì máy tính và do đó khoa học máy tính không tồn tại. Tất cả đều quay trở lại đầu những năm 1930, ngay cả trước những thử nghiệm đầu tiên của Konrad Zuse (dù sao không thể lập trình và / hoặc Turing hoàn thành). Họ chỉ nói về "các hàm tính toán trên các số tự nhiên".
Bây giờ, hóa ra, có rất nhiều bạn có thể biểu thị dưới dạng các hàm trên số tự nhiên - xét cho cùng, các máy tính hiện đại của chúng ta thậm chí còn hoạt động ít hơn thế (về cơ bản là 3-4 hàm trên các số 0 và 1, và đó là ), nhưng, ví dụ, hệ điều hành có chức năng gì?
Khái niệm I / O này, tác dụng phụ, tương tác với môi trường, không bị bắt bởi ý tưởng "các hàm trên số tự nhiên". Tuy nhiên, điều này rất quan trọng, vì, Simon Peyton Jones đã từng nói rằng "Tất cả chức năng thuần túy không có tác dụng phụ nào, làm cho CPU của bạn nóng lên" , mà một thành viên khán giả đã trả lời "thực sự, đó là một mặt -có hiệu quả quá! "
Edwin Brady , nhà thiết kế của Idris , (chỉ một nửa) sử dụng một cách đùa cợt (tôi không biết liệu anh ta có phát minh ra nó không) thuật ngữ "Tetris-Complete" để diễn tả sự khác biệt này giữa "có thể tính toán bất kỳ hàm tính toán nào trên các số tự nhiên" và "có thể được sử dụng để viết các chương trình không tầm thường tương tác với môi trường ". Trớ trêu hơn nữa, anh ta chứng minh điều này bằng cách thực hiện một bản sao Kẻ xâm lược không gian trong Idris , nhưng anh ta nói rằng anh ta tin tưởng rằng Tetris giảm xuống cho Kẻ xâm lược không gian.
Một điều cần chỉ ra là không chỉ là Turing-tương đương không nhất thiết phải đủ để nói về việc viết chương trình "hữu ích", nó có thể OTOH cũng thậm chí không được necesssary . Ví dụ: SQL chỉ trở nên tương đương Turing với ANSI SQL: 1999 , nhưng nó vẫn hữu ích trước đó. Trên thực tế, một số người có thể lập luận rằng làm cho nó tương đương với Turing chưa thêm vào tính hữu dụng của nó. Có nhiều ngôn ngữ dành riêng cho tên miền không tương đương với Turing. Ngôn ngữ mô tả dữ liệu thường không (và không nên). Total Languages rõ ràng không thể tương đương với Turing, nhưng bạn vẫn có thể viết các vòng lặp sự kiện, máy chủ web hoặc hệ điều hành trong đó. Cũng có những ngôn ngữ tương đương với Turing nhưng trong đó điều này thực sự được coi là một sai lầm.
Vì vậy, tất cả trong tất cả, Turing-tương đương không phải là quá thú vị, trừ khi bạn muốn phân tích tĩnh các chương trình.
Biểu cảm
Giả sử rằng hệ thống tính toán của chúng tôi đủ mạnh về mặt tính toán để thậm chí giải quyết vấn đề của chúng tôi, điều chúng tôi phải làm tiếp theo là thể hiện thuật toán của chúng tôi để giải quyết vấn đề đó theo một loại ký hiệu chính thức nào đó cho hệ thống đó. Nói cách khác: chúng ta cần viết một chương trình bằng một số ngôn ngữ máy tính. Đó là nơi mà khái niệm biểu cảm xuất hiện .
Về cơ bản, nó đề cập đến việc "dễ dàng" hay "thú vị" như thế nào khi viết chương trình của chúng tôi bằng ngôn ngữ lập trình cụ thể của chúng tôi. Như bạn có thể thấy, khái niệm này khá mơ hồ, chủ quan và mang tính tâm lý nhiều hơn là kỹ thuật.
Tuy nhiên, có những nỗ lực tại các định nghĩa chính xác hơn. Cuốn sách nổi tiếng nhất (và khắt khe nhất mà tôi biết) là của Matthias Felleisen trong bài viết về Sức mạnh biểu cảm của ngôn ngữ lập trình (hai trang đầu tiên có phần giới thiệu nhẹ nhàng, phần còn lại của bài báo có nhiều thịt hơn).
Trực giác chính là thế này: khi dịch một chương trình từ ngôn ngữ này sang ngôn ngữ khác, một số thay đổi bạn cần thực hiện được chứa cục bộ (ví dụ như biến FOR
vòng lặp thành WHILE
vòng lặp hoặc vòng lặp thành GOTO
s có điều kiện ) và một số yêu cầu thay đổi toàn cầu cấu trúc của chương trình.
Khi bạn có thể thay thế một tính năng của một ngôn ngữ bằng một tính năng khác của ngôn ngữ khác bằng cách chuyển đổi cục bộ, thì các tính năng này được cho là không có tác dụng đối với sức mạnh biểu cảm. Đây được gọi là đường cú pháp .
Mặt khác, nếu nó yêu cầu thay đổi cấu trúc toàn cầu của chương trình, thì ngôn ngữ bạn đang dịch được cho là không thể diễn tả tính năng này. Và ngôn ngữ bạn đang dịch từ được cho là biểu cảm hơn (đối với tính năng này).
Lưu ý rằng điều này đưa ra một định nghĩa khách quan có thể đo lường được về tính biểu cảm. Cũng lưu ý rằng khái niệm này phụ thuộc vào ngữ cảnh vào tính năng và nó mang tính so sánh. Vì vậy, nếu tất cả các chương trình trong ngôn ngữ Một có thể được dịch sang ngôn ngữ B với chỉ thay đổi địa phương, và có ít nhất một chương trình bằng ngôn ngữ B mà có thể không được dịch sang Một chỉ thay đổi địa phương, sau đó ngôn ngữ B là đúng biểu cảm hơn ngôn ngữ Một. Tuy nhiên, kịch bản nhiều khả năng là nhiều chương trình ở cả hai ngôn ngữ có thể được dịch qua lại, nhưng có một số chương trình ở cả hai ngôn ngữ không thể dịch sang ngôn ngữ khác. Điều này có nghĩa là không ngôn ngữ nào biểu cảm rõ ràng hơn ngôn ngữ kia, chúng chỉ có các tính năng khác nhau cho phép các chương trình khác nhau được thể hiện theo những cách khác nhau.
Điều này đưa ra một định nghĩa chính thức về ý nghĩa của việc "biểu cảm hơn", nhưng nó vẫn không nắm bắt được các khái niệm tâm lý đằng sau hiện tượng này. Ví dụ, đường cú pháp, theo mô hình này, không làm tăng sức mạnh biểu cảm của ngôn ngữ, bởi vì nó có thể được dịch chỉ bằng những thay đổi cục bộ. Tuy nhiên, chúng tôi biết từ kinh nghiệm rằng có FOR
, WHILE
và IF
có sẵn, ngay cả khi chúng chỉ là đường cú pháp cho điều kiện GOTO
làm cho việc thể hiện ý định của chúng tôi dễ dàng hơn .
Thực tế là, các ngôn ngữ khác nhau có các tính năng khác nhau giúp thể hiện cách suy nghĩ khác nhau về một vấn đề dễ hơn hoặc khó hơn. Và một số người có thể tìm thấy một cách để thể hiện ý định của họ dễ dàng hơn và những người khác theo một cách khác.
Một ví dụ tôi tìm thấy trong thẻ Ruby trên StackOverflow: nhiều người dùng theo dõi thẻ Ruby cho rằng các vòng lặp dễ hiểu hơn đệ quy và đệ quy chỉ dành cho các lập trình viên chức năng nâng cao và các vòng lặp trực quan hơn cho người mới, nhưng tôi đã thấy nhiều trường hợp hoàn thành những người mới trực giác viết mã như thế này:
def rock_paper_scissors
get_user_input
determine_outcome
print_winner
rock_paper_scissors # start from the top
end
Điều này thường dẫn đến một số người bình luận rằng "điều này không hiệu quả" và "họ đang làm sai" và "cách chính xác" là:
def rock_paper_scissors
loop do
get_user_input
determine_outcome
print_winner
end
end
Vì vậy, rõ ràng, có một số người mà đệ quy đuôi là một cách tự nhiên hơn để diễn tả khái niệm "vòng lặp" hơn là các cấu trúc vòng lặp.
Tóm lược
Thực tế là hai ngôn ngữ tương đương với Turing nói lên một và chính xác một điều: chúng có thể tính toán cùng một bộ hàm trên các số tự nhiên như một máy Turing có thể. Đó là nó.
Nó không nói bất cứ điều gì về việc họ tính toán các hàm đó nhanh như thế nào. Nó không nói bất cứ điều gì về việc dễ dàng thể hiện các chức năng đó. Và nó không nói bất cứ điều gì khác về những gì họ có thể làm ngoài chức năng tính toán trên các số tự nhiên (ví dụ: liên kết đến thư viện C, đọc đầu vào từ người dùng, ghi đầu ra ra màn hình).
điều đó có nghĩa là lớp các vấn đề mà mỗi ngôn ngữ lập trình có thể giải quyết thay đổi theo ngôn ngữ, mặc dù các ngôn ngữ này đã hoàn tất?
Đúng.
- Có những vấn đề không được đề cập trong thuật ngữ "Turing-Complete" (chỉ liên quan đến chức năng tính toán trên các số tự nhiên) như in ra màn hình. Hai ngôn ngữ có thể là Turing-Complete nhưng một ngôn ngữ có thể cho phép in ra màn hình và ngôn ngữ kia thì không.
- Ngay cả khi cả hai ngôn ngữ có thể giải quyết cùng một vấn đề, điều đó không nói lên điều gì về mức độ phức tạp của mã hóa và việc thể hiện mã hóa này dễ dàng như thế nào. Ví dụ: C có thể giải quyết mọi vấn đề mà Haskell có thể, chỉ đơn giản bằng cách viết trình thông dịch Haskell bằng Cọ nhưng trước tiên bạn phải viết trình thông dịch Haskell để giải quyết vấn đề theo cách này!