Tại sao hầu hết các ngôn ngữ lập trình không lồng ý kiến ​​khối?


18

Một số ít làm, nhưng không phải bất kỳ trong số những người nổi tiếng như tôi biết. Có điều gì xấu về ý kiến ​​lồng nhau?

Tôi dự định có các bình luận khối lồng trong ngôn ngữ (nhỏ) mà tôi đang làm việc, nhưng tôi muốn biết liệu đây có phải là một ý tưởng tồi hay không.


lại một vài câu trả lời: ohh, điều đó có ý nghĩa =) Tôi hoàn toàn làm bình luận khối lồng nhau rồi; mặc dù tôi có một giai đoạn từ vựng riêng biệt, nhưng đó không phải là loại SK-logic giới hạn được mô tả.

@Vuntic: Nếu bạn có một giai đoạn từ vựng riêng biệt sử dụng công cụ phức tạp hơn biểu thức thông thường, bạn có thể gặp vấn đề về hiệu suất. REs nhanh và dễ sử dụng bằng cách triển khai DFA.
David Thornley

Nó bắt lỗi nhiều hơn trước đó để không cho phép lồng

4
@David: ... hoàn toàn không. Nó thực sự rất nhanh.
amara

Tôi sẽ đề nghị rằng nếu bạn muốn cho phép các bình luận lồng nhau, bạn cho phép các thẻ bình luận bắt đầu được đánh dấu bằng mã thông báo và yêu cầu nếu một thẻ bình luận bắt đầu được đánh dấu, thì thẻ nhận xét kết thúc của nó phải được đánh dấu giống hệt nhau. Điều đó sẽ cho phép nhanh chóng xác định các thẻ bắt đầu / kết thúc không cân bằng và tránh khả năng xảy ra lỗi do các thẻ không cân bằng không được phát hiện.
supercat

Câu trả lời:


6

Một điều chưa ai đề cập đến, vì vậy tôi sẽ đề cập đến nó: Mong muốn lồng ý kiến ​​thường chỉ ra rằng lập trình viên đang làm sai.

Đầu tiên, chúng ta hãy đồng ý rằng lần duy nhất "lồng" hoặc "không lồng" được hiển thị cho lập trình viên là khi lập trình viên viết một cái gì đó có cấu trúc như thế này:

do_something();
/* comment /* nested comment */ more comment */
do_something_else();

Bây giờ, khi một điều như vậy xuất hiện trong thực tế? Chắc chắn lập trình viên sẽ không viết những bình luận lồng nhau mà theo nghĩa đen giống như đoạn trích trên! Không, trong thực tế khi chúng ta lồng ý kiến ​​(hoặc ước chúng ta có thể lồng chúng), đó là vì chúng ta muốn viết một cái gì đó như thế này:

do_something();  /* do a thing */
/* [ajo] 2017-12-03 this turned out to be unnecessary
do_something_else(); /* do another thing */
*/

Và đây là BAD. Đây không phải là một mô hình mà chúng tôi (như các nhà thiết kế ngôn ngữ) muốn khuyến khích! Cách chính xác để viết đoạn trích trên là:

do_something();  /* do a thing */

Mã "sai" đó, bắt đầu sai hoặc bất kể đó là gì, không thuộc về cơ sở mã. Nó thuộc về, tốt nhất, trong lịch sử kiểm soát nguồn. Lý tưởng nhất là bạn sẽ không bao giờ viết mã sai để bắt đầu, phải không? Và nếu mã sai đang phục vụ một mục đích ở đó, bằng cách cảnh báo các nhà bảo trì không khôi phục nó vì một lý do nào đó, thì đó có lẽ là một công việc cho một nhận xét mã được viết tốt và có chủ ý. Cố gắng diễn đạt "không làm X" bằng cách chỉ để lại một số mã cũ làm X, nhưng nhận xét, không phải là cách dễ đọc hoặc hiệu quả nhất để ngăn mọi người làm X.

Tất cả điều này rút ra một quy tắc đơn giản mà bạn có thể đã nghe trước đây: Đừng bình luận ra mã. (Đang tìm kiếm các cụm từ này sẽ bật lên một nhiều của ý kiến trong thỏa thuận .)

Trước khi bạn hỏi: có, các ngôn ngữ như C, C # và C ++ đã cung cấp cho lập trình viên một công cụ khác để "nhận xét" các khối mã lớn : #if 0. Nhưng đây chỉ là một ứng dụng cụ thể của bộ tiền xử lý C, đây là một công cụ lớn và hữu ích theo đúng nghĩa của nó. Nó thực sự sẽ vô cùng khó khăn và đặc biệt đối với một ngôn ngữ để hỗ trợ biên dịch có điều kiện #ifkhông hỗ trợ #if 0.


Vì vậy, chúng tôi đã thiết lập rằng các bình luận lồng nhau chỉ có liên quan khi lập trình viên đang bình luận ra mã; và chúng tôi đã thành lập (thông qua sự đồng thuận của rất nhiều lập trình viên có kinh nghiệm) rằng nhận xét mã là một điều xấu.

Để hoàn thành tam đoạn luận, chúng ta phải chấp nhận rằng các nhà thiết kế ngôn ngữ có mối quan tâm đến việc quảng bá những điều tốt và làm nản lòng những điều xấu (giả sử rằng tất cả những thứ khác đều bằng nhau).

Trong trường hợp các bình luận lồng nhau, tất cả các bình luận khác đều bằng nhau - bạn có thể bỏ qua các câu trả lời được bỏ phiếu thấp một cách an toàn cho rằng phân tích cú pháp lồng nhau /*sẽ gây khó khăn cho trình phân tích cú pháp. (Lồng nhau /*không khó hơn lồng nhau (, điều mà gần như mọi trình phân tích cú pháp trên thế giới đã cần xử lý.)

Vì vậy, tất cả những thứ khác đều bằng nhau, một nhà thiết kế ngôn ngữ có thể dễ dàng lồng các bình luận (nghĩa là để nhận ra mã), hay khó? Hãy nhớ lại rằng bình luận ra mã là một điều xấu.

QED


Chú thích. Lưu ý rằng nếu bạn không cho phép các bình luận lồng nhau, thì

hello /* foo*/bar.txt */ world

là một "bình luận" sai lệch - nó tương đương với

hello bar.txt */ world

(có khả năng là một lỗi cú pháp). Nhưng nếu bạn làm phép bình luận lồng nhau, sau đó

hello /* foo/*.txt */ world

là một "bình luận" sai lệch - nó tương đương với

hello

nhưng để bình luận mở hết cỡ đến cuối tập tin (một lần nữa gần như chắc chắn là lỗi cú pháp). Vì vậy, không có cách nào đặc biệt ít bị lỗi cú pháp không chủ ý. Sự khác biệt duy nhất là cách họ xử lý các phản hạt có chủ ý của mã nhận xét.


1
Tôi có ý kiến ​​khác nhau dựa trên thực tế đơn giản - tôi đã không nhìn thấy mọi thứ (và cả bạn cũng vậy). Vì vậy, trong khi những quy tắc vàng như "Đừng bình luận ra mã" trông thật tuyệt, cuộc sống có những con đường riêng. Trong trường hợp cụ thể này, tôi làm điều đó rất thường xuyên như chuyển đổi, khi tôi kiểm tra một số tính năng mới và phải tăng dần một số mã, vì vậy tôi nhận xét mã, sau đó ít hơn, ít hơn, ít hơn và cuối cùng tôi đã làm việc và tôi có thể loại bỏ tất cả các ý kiến ​​(qua mã). Ngôn ngữ hoàn hảo của tôi tất nhiên sẽ hỗ trợ các bình luận lồng nhau :-).
greenoldman

@greenoldman: Hầu hết các ngôn ngữ không có nhận xét lồng nhau, nhưng chúng sẽ có một số tính năng thực tế để "xóa một khối mã" ít được sử dụng hơn tính năng "để lại nhận xét". C's #if DEADlà ví dụ điển hình và được thiết kế tốt nhất. Trong nhiều ngôn ngữ, bạn có thể chỉ cần bọc mã chết tương đương if (DEAD). Và trong nhiều IDE, bạn thực sự có thể loại bỏ mã chết và dựa vào Ctrl + Z và / hoặc kiểm soát phiên bản để lấy lại nếu bạn muốn. Để lại một bình luận, chuỗi, bất cứ điều gì, có văn bản là một loạt các mã chết, vẫn là lựa chọn tồi tệ nhất cho khả năng đọc.
Quuxplusone

11

Bởi vì hầu hết các triển khai đang sử dụng các giai đoạn lexing và phân tích cú pháp riêng biệt, và để lexing chúng sử dụng các biểu thức chính quy cũ đơn giản. Nhận xét được coi là khoảng trắng - nghĩa là các mã thông báo bị bỏ qua và do đó nên được giải quyết hoàn toàn trong một lần vượt qua. Ưu điểm duy nhất của phương pháp này là phân tích tốc độ. Nhiều nhược điểm bao gồm các hạn chế nghiêm trọng về cú pháp (ví dụ: cần duy trì một bộ từ khóa cố định, không phụ thuộc vào ngữ cảnh).


3
Tôi sẽ không đồng ý với "hầu hết" ngày nay. Chắc chắn đó là cách truyền thống, nhưng tôi biết rằng đối với C, EDG kết hợp bộ tiền xử lý, từ vựng và phân tích cú pháp, và tôi nghi ngờ rằng cả GCC và Microsoft cũng vậy. Lợi ích là nó cho phép bạn thực hiện chúng một cách riêng biệt nếu bạn cần.
Andrew Aylett

Clang cũng đang làm như vậy. Nhưng đó vẫn chỉ là một tỷ lệ nhỏ trong các trình biên dịch ngôn ngữ phổ biến hiện có.
SK-logic

@Neil Butterworth, hãy xem mcs, javac, gcc (vâng, nó vá lại một lexer, nhưng nó vẫn là một lexing pass chuyên dụng), clang (giống như gcc), dmd, fpc, và nhiều, nhiều hơn nữa.
SK-logic

Không ai đang sử dụng các biểu thức chính quy trong từ vựng của họ cho bất kỳ trình biên dịch không tầm thường nào.
Nuoji

@Nuoji - đối với người không tầm thường - chắc chắn. Nhưng những người dựa vào flex và các công cụ tương tự làm.
SK-logic

7

Hoàn toàn có thể tạo ra một từ vựng có thể xử lý các bình luận lồng nhau. Khi nó ăn khoảng trắng, khi nó nhìn thấy /*nó có thể tăng bộ đếm độ sâu và giảm nó khi nhìn thấy */và dừng lại khi độ sâu bằng không. Điều đó nói rằng, tôi đã thực hiện nhiều trình phân tích cú pháp và không bao giờ tìm thấy lý do chính đáng để các bình luận lồng nhau.

Nếu các bình luận có thể lồng nhau, thì một nhược điểm là dễ khiến cho kết thúc của chúng không cân bằng và trừ khi bạn có một trình soạn thảo ưa thích, nó có thể ẩn mã vô hình mà bạn cho là có.

Mặt trái của những bình luận không làm tổ là một cái gì đó như thế này:

/*
some code
more code
blah blah blah
/**/

nơi bạn có thể dễ dàng nhận xét mã vào hoặc ra bằng cách xóa hoặc thêm dòng đầu tiên - chỉnh sửa 1 dòng. Tất nhiên, nếu bản thân mã đó chứa một nhận xét, điều này sẽ bị hỏng, trừ khi bạn cũng cho phép //nhận xét kiểu C ++ trong đó. Vì vậy, đó là những gì tôi có xu hướng làm.


1
//ý kiến ​​cũng theo phong cách C99.
JAB

Ngoài ra, một ngôn ngữ có thể chỉ định bắt đầu nhận xét là /*$token, trong đó identifiercó bất kỳ mã thông báo chữ và số nào và cuối nhận xét là token$*/. Sẽ tương đối đơn giản đối với mã thông báo bao gồm mã để xác minh rằng mọi dấu hiệu nhận xét kết thúc đều chứa mã thông báo phù hợp cho khối bắt đầu nhận xét phù hợp.
supercat

5

Vì không ai khác đề cập đến nó, tôi sẽ liệt kê một vài ngôn ngữ hỗ trợ các bình luận lồng nhau: Rexx, Modula-2, Modula-3, Oberon. Mặc dù tất cả các khiếu nại ở đây về các vấn đề khó khăn và tốc độ, không ai trong số họ dường như có bất kỳ vấn đề lớn.


4
Tôi thêm vào: Haskell, Frege
Ingo

Được hỗ trợ bởi Scala quá.
Matt R

4

Một điểm hay của các nhận xét khối lồng nhau là bạn có thể nhận xét các phần lớn của mã một cách dễ dàng (tốt, hầu như, trừ khi bạn có chuỗi kết thúc nhận xét khối trong một chuỗi hằng).

Một phương pháp khác là thêm vào một loạt các dòng với trình tự bắt đầu nhận xét dòng nếu bạn có một trình soạn thảo hỗ trợ nó.

Haskell đã lồng các bình luận khối, nhưng hầu hết mọi người dường như không chú ý hoặc phàn nàn về nó. Tôi đoán điều này là do những người không mong đợi các bình luận lồng nhau có xu hướng tránh chúng vì đây sẽ là một lỗi từ vựng trong các ngôn ngữ khác.


3

Hỗ trợ các bình luận khối lồng nhau làm phức tạp trình phân tích cú pháp, đây là công việc nhiều hơn và nó có thể làm tăng thời gian biên dịch. Tôi đoán nó không phải là một tính năng rất cần thiết cho một ngôn ngữ, vì vậy tốt hơn là sử dụng thời gian và nỗ lực cho các cải tiến và tối ưu hóa khác.

Theo tôi sự đơn giản luôn là một điều tốt trong việc thiết kế bất cứ thứ gì. Hãy nhớ rằng việc thêm một tính năng sẽ dễ dàng hơn việc xóa nó. Khi bạn cho phép nhận xét lồng nhau và có các chương trình sử dụng nó, bạn sẽ không thể đưa chúng ra mà không phá vỡ tính tương thích.


1
+1 cho "dễ dàng thêm một tính năng hơn là xóa nó".
R ..

3
một khi bạn không cho phép các bình luận lồng nhau, bạn cũng không thể cho phép các bình luận đó bởi vì nó sẽ phá vỡ các bình luận đó:/*/**/
Rịa

2

Một lý do có thể xảy ra là các bình luận lồng nhau phải được xử lý bởi trình phân tích cú pháp, vì hương vị của các biểu thức chính quy thường được sử dụng trong các từ vựng không hỗ trợ đệ quy. Những cái đơn giản có thể được loại bỏ dưới dạng khoảng trắng bởi lexer, vì vậy chúng đơn giản hơn để thực hiện theo cách đó.


3
Đó không phải là "hương vị". Từ "chính quy" trong biểu thức chính quy vốn đã loại trừ đệ quy.
R ..

3
@R: Trong toán học, chắc chắn. Nhưng trong lập trình, chúng ta có những thứ mà chúng ta gọi là regexes hỗ trợ đệ quy.
amara

Câu hỏi là: Đây có phải là một vấn đề? Hầu hết các ngôn ngữ đã phải đối phó với dấu ngoặc đơn lồng nhau. Để đặt tên cho một số: Lisp, C, Java, Python, Ruby, Perl.
Thomas Eding

Dấu ngoặc đơn lồng nhau là tốt, bởi vì những thứ bên trong dấu ngoặc đơn giống như những thứ bên ngoài: mã thông thường. Trong các bình luận, bạn không có mã thông báo, bạn chỉ cần có văn bản. Bạn cần có thể khớp các mã thông báo nhận xét bắt đầu và kết thúc để bạn biết liệu 'int' là một loại hay chỉ là một từ trong một nhận xét. (Đặc biệt nếu bạn loại bỏ các bình luận trong từ vựng.)
Alan Shutko

2
@ThePopMachine: Tôi chắc chắn về những gì tôi đã nêu, rằng thông thường có nghĩa chính thức được xác định, không phải ý nghĩa bạn đang sử dụng và "thông thường" trong "biểu thức chính quy" được chọn cho ý nghĩa này. Không đệ quy là một kết quả của định nghĩa của nó.
R ..

-1

Ai biết? Tôi đoán bởi vì việc hỗ trợ các bình luận lồng nhau là công việc nhiều hơn - bạn sẽ phải duy trì một nhóm sắp xếp nào đó, và vì nó làm phức tạp ngữ pháp ngôn ngữ.


-1

Bình luận lồng nhau có nghĩa là công việc thêm cho trình phân tích cú pháp. Thông thường khi bạn nhìn thấy bắt đầu một bình luận, bạn bỏ qua mọi thứ cho đến khi đánh dấu bình luận kết thúc. Để hỗ trợ các bình luận lồng nhau, bạn cũng phải phân tích văn bản trong các bình luận. Tuy nhiên, vấn đề lớn nhất là một lập trình viên phải cẩn thận để đóng tất cả các bình luận lồng nhau một cách chính xác nếu không sẽ dẫn đến lỗi biên dịch. Thực hiện đúng trình biên dịch là một việc có thể làm nhưng việc theo dõi các bình luận lồng nhau vì một lập trình viên khá dễ bị lỗi và khó chịu.


3
-1: không đúng. Trình phân tích cú pháp Sane không hoạt động như vậy.
amara
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.