Các nhà thiết kế ngôn ngữ làm gì để quyết định hoặc chứng minh rằng một tính năng cụ thể hoạt động chính xác?


11

Tôi quan tâm đến thiết kế ngôn ngữ và nói chung tôi có thể dễ dàng suy luận về các tính năng được biết đến rộng rãi (ví dụ: kế thừa, đa hình, đại biểu, lambdas, chụp, thu gom rác, ngoại lệ, tổng quát, phương sai, phản xạ, v.v.), các tương tác của chúng trong một ngôn ngữ cụ thể, những cách họ có thể thực hiện, những hạn chế của họ, v.v.

Trong vài tháng gần đây, tôi bắt đầu đọc về Rust, nơi có hệ thống sở hữu đảm bảo an toàn bộ nhớ và quản lý tài nguyên xác định bằng cách buộc tuổi thọ của đối tượng phải được kiểm chứng tĩnh. Từ quan điểm của một người sử dụng ngôn ngữ đơn giản, tôi có thể nhận hệ thống gần như ngay lập tức.

Tuy nhiên, từ quan điểm của một nhà thiết kế ngôn ngữ, tôi phải mất một thời gian để nhận ra lý do tại sao mọi thứ trong Rust lại chính xác như vậy. Tôi không thể hiểu ngay lý do đằng sau một số hạn chế của hệ thống sở hữu, cho đến khi tôi buộc mình phải đưa ra các trường hợp vi phạm tính toàn vẹn của hệ thống nếu nó không có những khía cạnh đó.

Câu hỏi chính của tôi không liên quan gì đến Rust và quyền sở hữu của nó cụ thể - nhưng hãy thoải mái sử dụng nó làm ví dụ trong nhận xét / câu trả lời của bạn, nếu bạn cần.

Khi các nhà thiết kế ngôn ngữ thiết kế một tính năng mới, họ sử dụng phương pháp hoặc quy trình nào để quyết định rằng tính năng đó hoạt động đúng?

Bởi "mới" Tôi có nghĩa là nó không phải là thứ đã được thử nghiệm trong các ngôn ngữ hiện có (và do đó, phần lớn công việc đã được thực hiện bởi các nhà thiết kế khác). Bằng cách "hoạt động đúng" Tôi có nghĩa là tính năng này giải quyết vấn đề dự định một cách chính xác và nó có khả năng chống đạn hợp lý. Bởi "chống đạn hợp lý" Tôi có nghĩa là không có mã nào có thể được viết bằng ngôn ngữ hoặc một tập hợp con cụ thể của ngôn ngữ (ví dụ: một tập hợp con không có mã "không an toàn") sẽ vi phạm tính toàn vẹn của tính năng.

  • Đây có phải là một quá trình thử nghiệm và lỗi, theo nghĩa là bạn đưa ra một hình thức đơn giản của tính năng, sau đó cố gắng tìm cách vi phạm nó, sau đó vá nó nếu bạn vi phạm thành công, sau đó lặp lại? Và sau đó, khi bạn không thể nghĩ ra bất kỳ vi phạm nào khác có thể xảy ra, bạn có hy vọng không còn gì và gọi đó là một ngày không?

  • Hoặc có một cách chính thức để thực sự chứng minh (theo nghĩa toán học của từ này) rằng tính năng của bạn hoạt động và sau đó sử dụng bằng chứng đó để tự tin có được tính năng đúng (hoặc chủ yếu là đúng) ngay từ đầu?

(Tôi nên đề cập rằng tôi có nền tảng kỹ thuật, không phải khoa học máy tính. Vì vậy, nếu tôi thiếu thứ gì đó rõ ràng với người CS, xin vui lòng chỉ ra.)


Khi bạn nói "nhà thiết kế ngôn ngữ", bạn có nghĩa là một người tạo ra trình biên dịch, hoặc chỉ cú pháp, hoặc cả hai?
Snoop

6
@StevieV: Thiết kế ngôn ngữ khác biệt và độc lập với việc thực hiện. Ví dụ, Lisp được thiết kế bởi John McCarthy như một cách dễ dàng hơn để nắm bắt thay thế cho phép tính. Tuy nhiên, anh đã không thực hiện nó. Trên thực tế, khi học trò Steve Russell muốn thực hiện Lisp, McCarthy nói với anh rằng anh tin rằng không thể thực hiện Lisp! APL được thiết kế như một ngôn ngữ để dạy toán học. Sau đó, IBM đã sử dụng nó để chính thức chỉ định hành vi của Hệ thống / 360 mà ngôn ngữ có một số phần mở rộng. Tại thời điểm này, nó vẫn chưa được thực hiện. Plankalkül được thiết kế bởi Konrad
Jörg W Mittag

4
Zuse 1942-1946 nhưng chỉ được thực hiện vào năm 1975. Niklaus Wirth lần đầu tiên thiết kế hoàn toàn ngôn ngữ của mình và chỉ thực hiện chúng sau khi hoàn thành thiết kế (và ông đã viết trình biên dịch đầu tiên bằng ngôn ngữ để cảm nhận ngôn ngữ tốt như thế nào được thiết kế - sau đó ông đã cho các sinh viên của mình dịch tay trình biên dịch sang ngôn ngữ khác để bootstrapping). Rất nhiều ngôn ngữ hàn lâm hơn không bao giờ được thực hiện, chúng chỉ được thiết kế để chứng minh một điểm hoặc thử nghiệm với một số tính năng ngôn ngữ theo một cách trừu tượng. Smalltalk được tạo ra là kết quả của một vụ cá cược lẫn nhau: Alan Kay đặt cược rằng anh ta có thể
Jörg W Mittag

3
thiết kế một ngôn ngữ hướng đối tượng trên một trang giấy, Dan Ingalls đặt cược rằng anh ta có thể thực hiện ngôn ngữ đó trong một vài ngày. (Và anh ấy đã làm nó trong BASIC, trong tất cả các ngôn ngữ!) Ngôn ngữ là các đối tượng toán học tồn tại độc lập với trình biên dịch / trình thông dịch của chúng. Và chúng có thể được thiết kế, nghiên cứu và thảo luận độc lập với bất kỳ triển khai vật lý nào.
Jörg W Mittag

3
Phải đọc: Godel, Escher, Bach . Đôi khi hơi kỳ quặc, nhưng đến cuối cùng, phần lớn công việc của Turing & Godel ảnh hưởng lớn đến hình thức của thiết kế ngôn ngữ.
RubberDuck

Câu trả lời:


6

Tôi đang gặp khó khăn trong việc tìm kiếm tài liệu tham khảo chính xác tại thời điểm này, nhưng một thời gian trước tôi đã xem một số video của Simon Peyton Jones , người đóng góp chính cho thiết kế của Haskell. Anh ấy là một diễn giả xuất sắc về lý thuyết loại, thiết kế ngôn ngữ, và tương tự, và có rất nhiều video có sẵn miễn phí trên youtube.

Haskell có một đại diện trung gian về cơ bản là phép tính lambda được tăng cường với một vài điều đơn giản để làm việc dễ dàng hơn. Tính toán Lambda đã được sử dụng và chứng minh vì máy tính chỉ là một người tính toán mọi thứ. Một điểm thú vị mà Simon Peyton Jones thường đưa ra là bất cứ khi nào họ làm điều gì đó điên rồ và điên cuồng với ngôn ngữ, anh ta biết rằng về cơ bản âm thanh của nó khi cuối cùng nó giảm xuống ngôn ngữ trung gian đó.

Các ngôn ngữ khác gần như không quá nghiêm ngặt, thay vào đó thiên về sự dễ sử dụng hoặc thực hiện. Họ làm những điều tương tự mà các lập trình viên khác làm để có được mã chất lượng cao: tuân theo các thực hành mã hóa tốt và kiểm tra nó cho đến chết. Một tính năng như ngữ nghĩa sở hữu của Rust Tôi chắc chắn nhận được cả rất nhiều phân tích và thử nghiệm chính thức để tìm ra các trường hợp bị lãng quên. Thông thường các tính năng như thế bắt đầu như luận án tốt nghiệp của ai đó.


2
Tôi tin rằng tài liệu tham khảo mà bạn đang tìm kiếm nằm trong một trong loạt "Cuộc phiêu lưu với các loại trong Haskell", có lẽ tài liệu này đưa ra nội dung của bảng trong hình ảnh thu nhỏ ...
Jules

8

Vì vậy, đối với thiết kế ngôn ngữ , có bằng chứng (hoặc lỗi). Ví dụ, loại hệ thống. Các loại và ngôn ngữ lập trình là cuốn sách kinh điển mô tả các hệ thống loại, và tập trung vào việc chứng minh tính đúng đắn và đầy đủ của hệ thống loại. Các ngữ pháp có phân tích tương tự và các thuật toán (như hệ thống sở hữu mà bạn mô tả) có riêng.

Để thực hiện ngôn ngữ , nó là mã như bất kỳ khác. Bạn viết bài kiểm tra đơn vị. Bạn viết bài kiểm tra tích hợp. Bạn làm mã đánh giá.

Điều duy nhất làm cho ngôn ngữ trở nên đặc biệt là chúng (hầu như luôn luôn) vô hạn. Bạn thực sự không thể kiểm tra cho tất cả các đầu vào. Và (lý tưởng nhất) chúng được sử dụng bởi hàng tấn người, làm những điều kỳ lạ và thú vị, do đó, bất kỳ lỗi nào trong ngôn ngữ sẽ được tìm thấy cuối cùng.

Trên thực tế , tương đối ít ngôn ngữ sử dụng bằng chứng để xác minh chức năng của chúng và kết thúc với một số hỗn hợp các tùy chọn bạn đề cập.


4
The only thing that makes languages special is that they are (almost always) infinite. You literally cannot test all inputs.Điều đó thực sự rất đặc biệt? Đó dường như là trường hợp phổ biến với tôi. Ví dụ: Hàm lấy danh sách làm đối số cũng có số lượng đầu vào vô hạn. Đối với mọi kích thước n bạn chọn, có một danh sách kích thước n + 1.
Doval

@doval - và chuỗi cũng vậy, tôi cho là vậy. Một điểm tốt.
Telastyn 18/03/2016

4

Điều đầu tiên và khó khăn nhất mà một nhà thiết kế ngôn ngữ phải quan tâm khi giới thiệu các tính năng mới, là giữ cho ngôn ngữ của anh ấy nhất quán:

  • làm thế nào nó có thể được tích hợp trong ngữ pháp ngôn ngữ mà không phá vỡ mã hiện có (điều này có thể được chứng minh về mặt toán học)
  • làm thế nào nó liên quan đến các tính năng hiện có (ví dụ: nếu bạn có các mảng cố định được lập chỉ mục 0..n-1, bạn sẽ không giới thiệu một tính năng mảng biến mới được lập chỉ mục 1..n) (đó là phần nghệ thuật của thiết kế)
  • Làm thế nào tính năng có thể được triển khai trên toàn bộ chuỗi công cụ để tính năng mới có thể được hấp thụ bởi hệ sinh thái, các nhà công cụ và lập trình viên (tính khả thi có thể được chứng minh bằng một bằng chứng về khái niệm, nhưng thực hiện đầy đủ là một cách tiếp cận tương tự như lập trình)

Để hướng dẫn trong vấn đề này, một nhà thiết kế dựa trên một bộ quy tắc và nguyên tắc thiết kế. Cách tiếp cận này được mô tả rất tốt trong " Thiết kế và tiến hóa của C ++ " từ Bjarne Stroustrup , một trong những cuốn sách hiếm hoi dành riêng cho thiết kế ngôn ngữ. Điều rất thú vị là thấy rằng các ngôn ngữ hiếm khi được thiết kế trong chân không và nhà thiết kế cũng nhìn cách ngôn ngữ của họ thực hiện các tính năng tương tự. Một nguồn khác (trực tuyến và miễn phí) là các nguyên tắc thiết kế cho ngôn ngữ java .

Nếu bạn nhìn vào các thủ tục tố tụng công khai của các ủy ban tiêu chuẩn hóa, bạn sẽ thấy rằng đó là một quá trình lỗi thử nghiệm. Dưới đây là một ví dụ về mô-đun C ++, một khái niệm hoàn toàn mới sẽ được giới thiệu trong phiên bản tiếp theo của ngôn ngữ. Và đây là một phân tích được soạn thảo sau một số thay đổi ngôn ngữ , để đánh giá thành công của nó. Và ở đây Quy trình cộng đồng Java để xác định các đặc tả Java mới, chẳng hạn như một api mới . Bạn sẽ thấy rằng công việc này được thực hiện bởi một số chuyên gia soạn thảo một cách sáng tạo một bài viết khái niệm và một đề xuất đầu tiên. Sau đó, các đề xuất này được xem xét bởi một cộng đồng / ủy ban lớn hơn có thể sửa đổi đề xuất để đảm bảo mức độ nhất quán cao hơn.


4

Làm thế nào để kiểm tra các tính năng ngôn ngữ lập trình? Đó là một câu hỏi rất hay, và tôi không chắc rằng tình trạng của nghệ thuật phụ thuộc vào công việc.

Mỗi tính năng mới có thể tương tác với tất cả các tính năng khác. (Điều này ảnh hưởng đến ngôn ngữ, tài liệu, trình biên dịch, thông báo lỗi, IDE, thư viện, v.v.) Các tính năng có kết hợp để mở ra một lỗ hổng không? Để tạo ra trường hợp cạnh khó chịu?

Ngay cả các nhà thiết kế ngôn ngữ rất thông minh làm việc chăm chỉ để duy trì âm thanh loại phát hiện ra các vi phạm như lỗi Rust này . Hệ thống loại của Rust không quá rõ ràng đối với tôi nhưng tôi nghĩ trong trường hợp này có vòng đời giá trị theo dõi hệ thống loại có nghĩa là "phân nhóm" trọn đời với các kỳ vọng về phân nhóm, ép buộc, tham chiếu và biến đổi thông thường, tạo ra một lỗ hổng trong staticsuốt cuộc đời ref có thể trỏ đến một giá trị được cấp phát ngăn xếp và sau đó trở thành một tham chiếu lơ lửng.

Bằng cách "hoạt động đúng" Tôi có nghĩa là tính năng này giải quyết vấn đề dự định một cách chính xác và nó có khả năng chống đạn hợp lý.

Đối với các ngôn ngữ dự định là ngôn ngữ sản xuất , được nhiều lập trình viên sử dụng để xây dựng phần mềm sản xuất đáng tin cậy, "hoạt động đúng" phải tiếp tục có nghĩa là giải quyết vấn đề dự định một cách chính xác cho đối tượng dự định.

Nói cách khác, khả năng sử dụng cũng quan trọng đối với thiết kế ngôn ngữ cũng như các loại thiết kế khác. Điều này đòi hỏi (1) thiết kế cho khả năng sử dụng (ví dụ: biết đối tượng của bạn) và (2) kiểm tra khả năng sử dụng.

Một bài viết ví dụ về chủ đề này là Lập trình viên là Người cũng vậy , Ngôn ngữ lập trình và các nhà thiết kế API có thể học được rất nhiều từ lĩnh vực thiết kế các yếu tố con người.

Một câu hỏi SE ví dụ về chủ đề này là Cú pháp của bất kỳ ngôn ngữ lập trình nào đã được kiểm tra khả năng sử dụng chưa?

Một ví dụ kiểm tra khả năng sử dụng đã xem xét mở rộng tính năng lặp lại danh sách (tôi không nhớ ngôn ngữ nào) để lấy nhiều danh sách. Mọi người có mong đợi nó lặp lại thông qua các danh sách song song hoặc thông qua các sản phẩm chéo không? Các nhà thiết kế ngôn ngữ đã rất ngạc nhiên bởi những phát hiện kiểm tra khả năng sử dụng.

Các ngôn ngữ như Smalltalk, Python và Dart được thiết kế chú trọng vào khả năng sử dụng. Rõ ràng Haskell thì không.


Haskell thực sự khá dễ sử dụng. Nó chỉ khó học vì nó là một mô hình hoàn toàn khác với Python / C / Java, v.v. Nhưng như một ngôn ngữ, nó khá dễ sử dụng.
dấu chấm phẩy
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.