Các ngôn ngữ lập trình phổ biến rất chắc chắn Turing-Complete, nếu bạn có một cái nhìn lý tưởng hóa nơi các chương trình có thể sử dụng một lượng lớn bộ nhớ tùy ý. Thông thường không có một tính năng nào mà bạn có thể cô lập mà không có ngôn ngữ nào sẽ không hoàn chỉnh.
Nói một cách trực giác, Turing hoàn thiện đòi hỏi hai điều:
- Một cách để các chương trình thao tác một lượng bộ nhớ không chỉ phụ thuộc vào kích thước của đầu vào. Bất kỳ hình thức tạo đối tượng đó có thể xây dựng những vật lớn từ các vật thể nhỏ là phù hợp: đối tượng, vật kiến trúc, cặp, danh sách,
malloc
, new
, vv Thậm chí ngăn xếp dựa trên phân bổ được đủ điều kiện là có một cách để đối tượng truy cập bất kỳ khoảng cách từ trên xuống của ngăn xếp (chỉ với phân bổ dựa trên ngăn xếp và chỉ truy cập vào đầu ngăn xếp, bạn chỉ nhận được một máy tự động đẩy xuống). Nhiều hình thức thao tác dữ liệu yếu hơn cũng phù hợp: ví dụ, trong một ngôn ngữ như Lisp hoặc Python nơi số nguyên không có kích thước giới hạn, chỉ các thao tác số nguyên cơ bản là đủ để hoàn thành Turing.
- Một cách để các chương trình tiếp tục chạy hoặc tạm dừng dựa trên một số phần của dữ liệu. Trong khi các vòng lặp, đệ quy cộng với một số dạng điều kiện (ví dụ
if
hoặc case
/ switch
) và goto
cộng với một số dạng điều kiện là ba cách phổ biến, nhưng có những cách khác.
Tôi nghĩ rằng cách tốt nhất để hiểu điều gì tạo nên một ngôn ngữ Turing-Complete là xem xét các ví dụ về các ngôn ngữ mạnh mẽ, nhưng không hoàn chỉnh Turing. Tôi sẽ đưa ra hai ví dụ minh họa hai họ chính của các ngôn ngữ đó (trừ các ngôn ngữ hoạt động trong bộ nhớ giới hạn).
Xem xét một ngôn ngữ bắt buộc với các hoạt động và mảng số nguyên, nhưng chỉ cho các vòng lặp ( for i = 1 to n
, trong đó i
không thể được sửa đổi trong vòng lặp), không phải các vòng lặp tùy ý (trong khi) và không có đệ quy. BlooP và các phiên bản đầu tiên của FORTRAN là ví dụ. Trong một ngôn ngữ như vậy, bạn chỉ có thể diễn tả các hàm đệ quy nguyên thủy - các hàm trong đó số lượng tính toán được giới hạn trong kích thước của đầu vào. Ngôn ngữ không phải là Turing-Complete - không thể biểu thị các hàm đệ quy tùy ý - do bị ràng buộc về thời gian tính toán.
Một ngôn ngữ chức năng có thể được thực hiện không hoàn chỉnh bằng cách hạn chế đệ quy thông qua một hệ thống loại hạn chế tất cả các chức năng được chấm dứt. Nếu hệ thống loại là có thể quyết định (nghĩa là nếu nó có thể quyết định liệu chương trình có được gõ tốt hay không), thì ngôn ngữ đó không thể là Turing-Complete (vì vấn đề tạm dừng là không thể giải quyết được). Các ngôn ngữ được sử dụng để chứng minh định lý, như Coq và Agda , thuộc loại này.
Xem thêm Idris không thể làm gì khi từ bỏ tính hoàn chỉnh của Turing?
Mặt khác, các định lý định lý yêu cầu người dùng nhập bằng chứng chấm dứt (nghĩa là họ không tự tìm thấy chúng). Vì vậy, bạn có thể thực hiện một định lý định lý với một hệ thống loại không thể giải quyết được: nếu bạn nhận được một bằng chứng chính xác, bạn sẽ vui, nếu không bạn sẽ bỏ cuộc sau một thời gian. Nhưng nó sẽ không thân thiện với người dùng. Hầu hết các provers định lý có một hệ thống loại có thể quyết định: bạn nhập một thuật ngữ và nó được chấp nhận hoặc bạn nhận được một lỗi loại. Những gì các nhà cung cấp định lý không có là loại suy luận có thể quyết định : nếu bạn nhập một thuật ngữ với thông tin loại một phần và nó bị từ chối, bạn không biết liệu đó có phải là thuật ngữ không thể gõ hay không vì công cụ suy luận không đủ thông minh.