Làm thế nào để xác minh / chứng minh tính trực giao của ngôn ngữ lập trình?


10

Tôi biết khái niệm về tính trực giao, nhưng từ quan điểm ngôn ngữ lập trình, có cách nào để xác minh / chứng minh điều đó không?

Ví dụ trong C #, người ta có thể sử dụng publichoặc staticcho chữ ký phương thức. Bạn có thể sử dụng một trong hai hoặc cả hai và chúng sẽ không can thiệp lẫn nhau, vì vậy chúng trực giao với nhau, phải không?

Câu hỏi của tôi là, làm thế nào để tôi đi về phần còn lại của các tính năng, đặc biệt là các tính năng không liên quan đến nhau?

Có phải tất cả các tính năng phải cùng tồn tại / xếp chồng lên nhau?

Có một ngôn ngữ lập trình là 100% trực giao?


Bắt đầu từ (gần) bắt đầu: ngôn ngữ lắp ráp?
Matthew Flynn

1
Để thực sự chứng minh một cái gì đó, bạn cần một định nghĩa chính thức cho nó. Và nếu định nghĩa của bạn sẽ là một cái gì đó lớn như thông số C #, việc chứng minh mọi thứ sẽ tốn rất nhiều công sức.
Svick

Câu trả lời:


4

Tôi không chắc chắn rằng tính trực giao có thể đóng vai trò là số liệu hữu ích hoặc hợp lệ trong trường hợp sử dụng các ngôn ngữ bậc cao như C #, vì nó đòi hỏi phải phân biệt "hoạt động" và "toán hạng" - những phần nhỏ của ngôn ngữ không dễ dàng phân biệt trong các ngôn ngữ bậc cao như C #.

Sự hiểu biết của tôi về tính trực giao dựa trên ngôn ngữ Trình biên dịch trong đó tính trực giao của tập lệnh của một CPU hoặc vi điều khiển cụ thể cho biết liệu có một số ràng buộc đối với các hoạt động được thực hiện bởi CPU hoặc bộ điều khiển này tùy thuộc vào loại dữ liệu. Trong thời gian đầu, điều này rất quan trọng vì không phải CPU nào cũng hỗ trợ các hoạt động trên các số phân số hoặc số có độ dài khác nhau, v.v.

Về mặt này, tôi muốn kiểm tra tính trực giao của Ngôn ngữ trung gian chung sử dụng ngôn ngữ Stack Machine làm mục tiêu cho trình biên dịch C #, chứ không phải chính C #.

Nếu bạn thực sự quan tâm đến tính trực giao của C # và tôi không nhầm ở đây (vì mục đích hoàn toàn) tôi sẽ đề nghị tìm kiếm một số thuật toán lập trình di truyền . Bạn có thể sử dụng những chương trình này để tạo các chương trình khác nhau từ bộ từ khóa nhất định (ngay cả những từ khóa vô nghĩa) và bạn chỉ có thể tự động kiểm tra xem chúng có thể biên dịch được không. Điều này sẽ giúp bạn tự động xem những yếu tố nào của ngôn ngữ có thể được kết hợp với nhau và rút ra một số khía cạnh của số liệu trực giao của bạn.


6

Thuật ngữ "tính trực giao" là thuật ngữ của một giáo dân cho một khái niệm toán học chính xác: các thuật ngữ ngôn ngữ tạo thành một đại số ban đầu (tra cứu nó trong Wikipedia).

Về cơ bản nó có nghĩa là "có một sự tương ứng 1-1 giữa cú pháp và ý nghĩa". Điều này có nghĩa là: có chính xác một cách để diễn đạt sự vật và, nếu bạn có thể đặt một số biểu thức ở một vị trí cụ thể, thì bạn cũng có thể đặt bất kỳ biểu thức nào khác ở đó.

Một cách khác để suy nghĩ về "trực giao" là cú pháp tuân theo nguyên tắc thay thế. Ví dụ: nếu bạn có một câu lệnh có một vị trí cho một biểu thức, thì bất kỳ biểu thức nào cũng có thể được đặt ở đó và kết quả vẫn là một chương trình hợp lệ về mặt cú pháp. Hơn nữa, nếu bạn thay thế

Tôi muốn nhấn mạnh rằng "ý nghĩa" không bao hàm kết quả tính toán. Rõ ràng, 1 + 2 và 2 + 1 đều bằng 3. Tuy nhiên các thuật ngữ là khác biệt và ngụ ý một phép tính khác nhau ngay cả khi nó có cùng kết quả. Ý nghĩa là khác nhau, giống như hai thuật toán sắp xếp là khác nhau.

Bạn có thể đã nghe nói về "cây cú pháp trừu tượng" (AST). Từ "trừu tượng" ở đây có nghĩa chính xác là "trực giao". Về mặt kỹ thuật hầu hết AST không thực sự trừu tượng!

Có lẽ bạn đã nghe nói về ngôn ngữ lập trình "C"? Ký hiệu loại C không trừu tượng. Xem xét:

int f(int);

Vì vậy, đây là một loại khai báo hàm trả về int. Loại con trỏ của hàm này được cho bởi:

int (*)(int)

Lưu ý, bạn không thể viết loại hàm! Ký hiệu loại C hút thời gian lớn! Nó không trừu tượng. Nó không trực giao. Bây giờ, giả sử chúng ta muốn tạo một hàm chấp nhận kiểu trên thay vì int:

int (*) ( int (*)(int) )

Tất cả đều ổn .. nhưng .. nếu chúng ta muốn trả lại thay thế:

int (*)(int) (*) (int)

Ái chà! Không hợp lệ. Cho phép thêm parens:

(int (*)(int)) (*) (int)

Ái chà! Điều đó cũng không hoạt động. Chúng ta phải làm điều này (đó là cách duy nhất!):

typedef int (intintfunc*) (int);
intintfunc (*)(int)

Bây giờ nó ổn, nhưng phải sử dụng một typedef ở đây là xấu. C hút. Nó không trừu tượng. Nó không trực giao. Đây là cách bạn làm điều này trong ML, đó là:

 int -> (int -> int)

Chúng tôi lên án C ở cấp độ cú pháp.

Ok, bây giờ hãy để flog C ++. Chúng tôi có thể khắc phục sự ngu ngốc ở trên bằng các mẫu và nhận được ký hiệu ML (ít nhiều):

fun<int, int>
fun< fun<int,int>, int>

nhưng hệ thống loại thực tế bị thiếu sót về cơ bản bởi các tham chiếu: nếu Tlà một loại, thì là T&một loại? Câu trả lời rất khó hiểu: ở cấp độ cú pháp, nếu bạn có loại U = T &, thì U & được cho phép nhưng nó chỉ có nghĩa là T &: tham chiếu đến tham chiếu là tham chiếu ban đầu. Thật tệ Nó phá vỡ yêu cầu duy nhất về mặt ngữ nghĩa. Tệ hơn: T & & không được phép về mặt cú pháp: điều này phá vỡ nguyên tắc thay thế. Vì vậy, các tham chiếu C ++ phá vỡ tính trực giao theo hai cách khác nhau, tùy thuộc vào thời gian ràng buộc (phân tích phân tích hoặc phân tích loại). Nếu bạn muốn hiểu làm thế nào để làm điều này đúng .. không có vấn đề gì với con trỏ!

Hầu như không có ngôn ngữ thực sự là trực giao. Ngay cả Scheme, giả vờ rõ ràng tuyệt vời của biểu thức, không. Tuy nhiên, nhiều ngôn ngữ tốt có thể được đánh giá là có "cơ sở tính năng trực giao hợp lý" và đó là một khuyến nghị tốt cho một ngôn ngữ, áp dụng cả cho cú pháp và ngữ nghĩa cơ bản.


Vì vậy, bạn nghĩ ML là trực giao hơn những người khác? Còn Lisp và Haskell thì sao?
Joan Venge

1
@joan: tốt, lisp không có bất kỳ tính năng nào vì vậy nó đáp ứng yêu cầu trong vaccuuo :)
Yttrill

@joan: Tôi không phải là lập trình viên Haskell nên hơi khó nói, nhưng sự hiện diện trong Haskell của "chức năng cực kỳ cao" là biểu hiện của tính trực giao mạnh mẽ: bạn chỉ đơn giản là không thể triển khai Monads hoặc Mũi tên phần còn lại của ngôn ngữ có "tính trực giao" đáng kể
Yttrill

Bạn nghĩ gì về Pascal. Có vẻ tải tốt hơn C.
supercat

Tôi biết nhận xét của tôi đã trễ gần 4 năm nhưng tôi mới bắt gặp nó. Câu trả lời này là sai về tất cả mọi thứ. Ngay cả toàn bộ "đó là cách duy nhất!" một phần đơn giản là sai. Bạn có thể dễ dàng diễn đạt điều đó mà không cần ví dụ typedef int (*intintfunc())(int) { ... }- intintfunc là một hàm không có đối số và trả về một con trỏ tới hàm lấy 1 đối số int và trả về giá trị int.
Wiz

4

Chứng minh tính trực giao đang chứng minh một tiêu cực. Điều đó có nghĩa là bạn không có bất kỳ cấu trúc nào không trực giao, điều đó có nghĩa là việc chứng minh một cái gì đó không trực giao sẽ dễ dàng hơn rất nhiều .

Trong thực tế, hầu hết mọi người nói về tính trực giao của các ngôn ngữ lập trình về mức độ thay vì hoàn toàn trực giao hoặc không. Khi kiến ​​thức từ việc làm một cái gì đó trong một bối cảnh chuyển sang bối cảnh khác và "làm những gì bạn mong đợi", ngôn ngữ đó được cho là trực giao hơn. LISP được coi là trực giao cao vì mọi thứ đều là danh sách, nhưng tôi không nghĩ có thể nói nó là trực giao 100% vì một số dự phòng giúp sử dụng dễ dàng hơn. C ++ được coi là không trực giao vì có rất nhiều "gotchas" nhỏ, nơi nó không hoạt động theo cách bạn nghĩ.


3

Cảnh báo, tôi không biết gì về chủ đề này.

Nhìn lướt qua Wikipedia dường như chỉ ra rằng Orthogonality chủ yếu hướng vào các mẫu thiết kế và thiết kế hệ thống. Về ngôn ngữ lập trình, mục nhập chỉ ra rằng các tập lệnh là trực giao nếu có một và chỉ một lệnh cho mỗi hành động có thể, hoặc đúng hơn, không có lệnh nào chồng lên nhau.

Đối với C #, tôi tưởng tượng rằng nó là trực giao, trong đó hầu hết các thủ thuật cú pháp ( foreachxuất hiện trong tâm trí) chỉ đơn giản là các giao diện được tạo thành đặc biệt của cấu trúc cơ sở ( foreachtrở thành forcác vòng lặp). Nhìn chung, ngôn ngữ chỉ thực sự hỗ trợ thực hiện mọi thứ theo một cách duy nhất, mặc dù đường cú pháp cung cấp các cách bổ sung để thực hiện chúng. Và cuối cùng, tất cả được biên dịch thành MSIL(hoặc bất cứ thứ gì nó được gọi là những ngày này) và MSILcó khả năng trực giao.

Nếu bạn thực hiện cảnh báo rằng công cụ đường tổng hợp về cơ bản là một "trình bao bọc" xung quanh việc thực hiện nó theo "cách khó", bạn có thể phân tích các tính năng khác nhau của ngôn ngữ, bỏ qua đường và xem liệu có bất kỳ cấu trúc nào thực sự trùng lặp. Nếu không, tôi tưởng tượng bạn có thể khai báo ngôn ngữ trực giao.

Theo quan điểm của tôi.


Tôi nghĩ rằng nếu cả for và foreach đều là đặc điểm của ngôn ngữ trong khi một ngôn ngữ là một cú pháp cú pháp của ngôn ngữ kia (trong đó hiệu ứng của foreach có thể đạt được bằng cách sử dụng), thì ngôn ngữ sẽ mất tính trực giao ở đó.
vpit3833

Không do...whilethể được sử dụng để cung cấp hiệu ứng tương tự như for? Tôi chưa bao giờ nghe nói về việc được coi là đường cú pháp.
Matthew Flynn

1
@MatthewFlynn: Bah! Chúng là đường cú pháp, bạn chỉ có thể thay thế phép lặp của mình bằng hàm đệ quy! ;)
Thất vọngWithFormsDesigner

2
@FrustratedWithFormsDesigner: Không phải đó chỉ là cú pháp cú pháp cho GOTO sao?
Ivan

2
@MatthewFlynn do whileđảm bảo thực hiện một vòng lặp duy nhất và kiểm tra điều kiện sau thực tế. forkiểm tra điều kiện trước và không đảm bảo thực hiện một lần.
Digitlworld

2

Câu hỏi của tôi là, làm thế nào để tôi đi về phần còn lại của các tính năng, đặc biệt là các tính năng không liên quan đến nhau?

Bạn tiếp tục làm những gì bạn đang làm, liệt kê tất cả các kết hợp hoạt động hoặc bị cấm.

Đó là tất cả. Nó khá đau để làm.

Có phải tất cả các tính năng phải cùng tồn tại / xếp chồng lên nhau?

Nếu tất cả các tính năng có thể được phân chia thành các tập hợp rời rạc mà không can thiệp lẫn nhau, thì chắc chắn, tất cả sẽ hợp lý.

Tất cả các cấu trúc dữ liệu làm việc với tất cả các loại nguyên thủy. Tất cả các toán tử biểu thức làm việc với tất cả các loại. Đó là những định nghĩa phổ biến về tính trực giao. Nhưng bạn có thể muốn nhiều hơn (hoặc ít hơn)

Tuy nhiên, đôi khi, có những trường hợp đặc biệt do hệ điều hành hoặc thư viện cũ không trực giao.

Ngoài ra, một số loại không thực sự rất phù hợp cả. Ví dụ Python cho phép bạn so sánh hai đối tượng từ điển để "đặt hàng". Nhưng hầu như không có định nghĩa hợp lý về "đặt hàng" giữa các từ điển. Python định nghĩa một, nhưng nó khá gây tranh cãi. Liệu trường hợp đặc biệt đó làm cho từ điển thất bại trong một bài kiểm tra trực giao?

Làm thế nào trực giao là "đủ trực giao"? Những gì bạn cần phải nhìn thấy được hạnh phúc với mức độ trực giao trong ngôn ngữ của bạn.


2

Danh sách các tính năng không chính thống thực sự dài trong hầu hết các ngôn ngữ lập trình, ví dụ:

  • mâu thuẫn các lớp xung đột với phản xạ java
  • xung đột xóa chung và loại với phản ánh java
  • mảng có phần khác với các đối tượng khác, vì loại đặc biệt của chúng, mặc dù chúng là các đối tượng.
  • phương thức tĩnh so với phương thức không giống nhau, ví dụ: bạn không thể ghi đè phương thức tĩnh
  • lớp lồng nhau là một suy nghĩ sau
  • tác động của việc gõ động so với gõ tĩnh đối với chiến lược gửi thư (xem ví dụ: trường hợp cạnh này trong C #)
  • Vân vân.

Đó chỉ là một vài thứ xuất hiện trong đầu tôi, nhưng có nhiều thứ khác, và cả những ngôn ngữ khác.

Thật khó để đảm bảo rằng không có sự giao thoa tinh tế giữa các tính năng ngôn ngữ. Như CAR Hoare chỉ ra trong bài báo "Gợi ý về thiết kế ngôn ngữ lập trình":

Một phần của thiết kế ngôn ngữ bao gồm sự đổi mới. Hoạt động này dẫn đến các tính năng ngôn ngữ mới trong sự cô lập. Phần khó nhất của thiết kế ngôn ngữ nằm ở sự tích hợp : chọn một tập hợp các tính năng ngôn ngữ hạn chế và đánh bóng chúng cho đến khi kết quả là một khung đơn giản nhất quán không có các cạnh thô hơn.

Có lẽ, một động thái tốt để tăng tính trực giao là thống nhất các khái niệm (đi theo hướng trả lời @ karl-bielfeld). Nếu tất cả mọi thứ là, nói một danh sách hoặc một đối tượng, rất có thể là sẽ có ít xung đột hơn. Hoặc thay vì có lớp lồng nhau sau khi nghĩ, hãy biến nó thành một tính năng cốt lõi.

Hầu hết các tài liệu ngôn ngữ lập trình chứng minh các thuộc tính nhất định của ngôn ngữ (ví dụ như âm thanh loại) trên một tập hợp con ("lõi") của ngôn ngữ được chính thức hóa. Ở đây chúng ta nên làm ngược lại, chứng minh rằng tất cả các tính năng sáng tác an toàn. Ngoài ra, điều đó có nghĩa là người ta nên định nghĩa "sáng tác" nghĩa là gì. Nó có nghĩa là "chạy"? (Trong trường hợp này, liên kết ở trên về trường hợp cạnh với kiểu gõ động và tĩnh là an toàn). Nó có nghĩa là "an toàn"? Liệu nó có nghĩa là có thể dự đoán được từ quan điểm của nhà phát triển?

Tất cả điều đó rất thú vị - nhưng cũng rất thách thức.

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.