Dấu chấm phẩy tùy chọn


10

Thông thường, trong một ngôn ngữ mệnh lệnh có mục đích chung - dấu chấm phẩy là dấu phân cách câu lệnh là bắt buộc hoặc không được phép hoàn toàn (ví dụ: C và Python).

Tuy nhiên, một số ngôn ngữ, như JavaScript, cho phép bạn từ chối phân định các câu lệnh của mình bằng dấu chấm phẩy, có lợi cho các dấu phân cách khác (chẳng hạn như một dòng mới).

Các quyết định thiết kế đằng sau này là gì? Tôi hiểu rằng dấu chấm phẩy rất cần thiết khi viết nhiều câu trên cùng một dòng, nhưng có lý do nào khác để bắt chúng không bắt buộc (ngoại trừ theo C) không?


1
Bạn cần suy nghĩ về các dấu kết thúc câu lệnh (perl, c) và dấu phân cách câu lệnh (javascript, pascal).

5
Trong Python, dấu chấm phẩy có thể được sử dụng để phân tách nhiều câu lệnh trên cùng một dòng. Và vì một câu lệnh "trống" được cho phép, dấu chấm phẩy có thể được sử dụng ở cuối hầu hết các câu lệnh.
Greg Hewgill

1
I understand that semicolons are essential when writing multiple statements on the same line- Phụ thuộc vào ngôn ngữ. Câu lệnh ưa thích của tôi hoàn toàn không có dấu phân cách như vậy, câu lệnh tiếp theo bắt đầu khi tất cả các đối số hàm đã được sử dụng hết.
Izkata

1
@MichaelT: Tôi không nghĩ cách phân loại của bạn là chính xác: Perl được cho là thuộc cả hai nhóm và JavaScript thực sự nằm trong trại "chấm dứt câu lệnh" (vì việc triển khai được yêu cầu để suy ra dấu chấm phẩy trước }hoặc cuối tập tin).
ruakh

Vâng, hoàn toàn phụ thuộc vào ngôn ngữ. Dự đoán cá nhân của tôi sẽ là dấu chấm phẩy chỉ là một loại quy ước thường được thống nhất, mà hầu hết các nhà thiết kế ngôn ngữ tuân theo. Ít nhất nó có ý nghĩa từ quan điểm ngôn ngữ giống như tự nhiên hơn. Tương tự với {và} cho các khối, nhân tiện: chúng được sử dụng bởi nhiều ngôn ngữ, tuy nhiên không phải tất cả và bạn thực sự không phải làm điều này. Không có lý do phổ quát đằng sau này.
JensG

Câu trả lời:


24

Làm cho chúng bắt buộc (hoặc không cho phép chúng hoàn toàn) làm giảm số lượng các trường hợp góc, loại bỏ nguồn tiềm ẩn của các lỗi tối nghĩa và đơn giản hóa thiết kế trình biên dịch / trình thông dịch.

Các nhà thiết kế ngôn ngữ đã chọn làm cho họ tùy chọn đã chọn sống với sự mơ hồ để đổi lấy sự linh hoạt cú pháp lớn hơn.


7
@RobertHarvey Dị giáo! Nên có một, cách rõ ràng để làm điều đó và chỉ có một. Ngẫu nhiên, chỉ có một cách để làm điều đó trong perl.

1
BTW - một số ngôn ngữ có lượng dư thừa khá lớn trong các ngữ pháp nói chung, do đó, việc tạo dấu chấm phẩy tùy chọn chỉ đôi khi mơ hồ trong thực tế. Điều đó nói rằng, tôi nghĩ rằng dấu chấm phẩy là một chút sai sót của sự dư thừa - tôi khá thích Haskell nơi bạn thả các dấu phẩy và dấu phẩy cho các đối số thay thế. OK, bạn cũng có thể bỏ dấu chấm phẩy trong Haskell, nhưng nó không thực sự giống với Javascript.
Steve314

2
Vấn đề của IIRC là chúng không phù hợp với mô hình chính thức nhưng các trình tạo trình phân tích cú pháp không tạo ra các thông báo lỗi tốt. Tức là họ có kiến ​​thức hạn chế về các lỗi phổ biến trong khi trình phân tích cú pháp viết tay có thể nhận được thông báo lỗi hữu ích hơn nhiều. Gcc ví dụ được sử dụng để sử dụng bison cho ngữ pháp C. Tương tự, vấn đề là 'trường hợp cạnh' không phải là trường hợp cạnh chính thức mà là trường hợp mềm - tức là đối với trình phân tích cú pháp, AST rõ ràng và đối với con người thì AST 'rõ ràng' nhưng họ không đồng ý AST là như thế nào.
Maciej Piechotka

2
@Maciej Piechotka - Tôi không có ý ám chỉ các parens là tùy chọn trong Haskell. Tôi đang nói về việc bỏ đi thứ gì đó dư thừa như một quyết định thiết kế ngôn ngữ. Vấn đề là bạn không sử dụng parens hoặc dấu phẩy cho một lệnh gọi hàm trong Haskell. Bạn có thể truyền một tuple làm đối số, nhưng đó vẫn là cú pháp cho một tuple, không phải để truyền các đối số. Haskell (và ML và những người khác) đã "bỏ" các dấu phẩy và dấu phẩy cho các đối số hàm theo nghĩa là có quy ước chung này trong các ngôn ngữ khác (kể từ Algol?), Nhưng Haskell không làm điều đó.
Steve314

1
@Maciej Piechotka - Tất nhiên nó không bao giờ thực sự là một quy ước phổ quát - chỉ vì ngôn ngữ của gia đình Algol không có nghĩa là các ngôn ngữ khác tự định nghĩa liên quan đến điều đó, vì vậy, yêu cầu "bỏ rơi" của tôi là sai theo nghĩa đó - nhưng với tất cả ngôn ngữ gia đình C ngày nay cảm thấy hơi giống như vậy.
Steve314

15

JavaScript đã cho chúng ta thấy rằng đây là một ý tưởng rất tồi. Ví dụ:

return
0;

Trong C, giá trị này trả về giá trị bằng 0. Trong JavaScript, giá trị này trả về undefinedvì dấu chấm phẩy được chèn sau câu lệnh return và không rõ ràng tại sao mã của bạn bị phá vỡ trừ khi bạn biết về chi tiết chèn dấu chấm phẩy tự động.


1
@delnan: Python không được thiết kế để trông giống C. Nó nổi tiếng là dựa trên thụt lề và do đó có tính định hướng cao và nó không yêu cầu dấu chấm phẩy. JavaScript về mặt kỹ thuật không yêu cầu chúng; nó chèn một cái khi nó tìm thấy một cái bị thiếu, nó biến đổi một thứ trông giống như một câu lệnh hợp lệ về mặt cú pháp thành hai câu khác biệt với ngữ nghĩa hoàn toàn khác nhau.
Mason Wheeler

7
Đó không phải là một ý tưởng tồi, nó chỉ gây nhầm lẫn cho những người cố gắng sử dụng JavaScript mà không bận tâm tìm hiểu về cách chèn dấu chấm phẩy tự động của nó . Có lẽ thay vì nói "đây là một ý tưởng rất tồi", bạn có thể nói chính xác hơn "làm dấu chấm phẩy tùy chọn giới thiệu những cạm bẫy cho các lập trình viên không đi ra ngoài và tìm hiểu tất cả các chi tiết".
TehShrike

4
@delnan: Lý do đáng ngạc nhiên là JavaScript thường không chèn dấu chấm phẩy ở cuối dòng, ngoại trừ để sửa một chương trình không hợp lệ. After returnlà một trong số ít các trường hợp JavaScript sẽ chèn dấu chấm phẩy ngay cả khi chương trình có hiệu lực nếu không có nó. (Nhưng tất nhiên, điều này làm suy yếu quan điểm của Mason Wheeler. Vấn đề không phải là dấu chấm phẩy là tùy chọn, đó là các quy tắc không nhất quán.)
ruakh

6
@TehShrike: Tạo dấu chấm phẩy tùy chọn giới thiệu cạm bẫy cho tất cả các lập trình viên, bởi vì nó tự ý diễn giải lỗi chính tả thay vì hỏi bạn ý của bạn là gì. Mọi người làm một lỗi đánh máy bây giờ và sau đó.
Jan Hudec

1
javascript đã chỉ ra rằng việc thực hiện các dấu chấm phẩy tùy chọn là thiếu sót. Nó không cho thấy dấu chấm phẩy tùy chọn là xấu mỗi lần.
CodeInChaos

4

Nó đơn giản hóa ngữ pháp và trình phân tích cú pháp của bạn phần nào để làm cho dấu chấm phẩy bắt buộc. Về cơ bản, nó cho phép lexer kết xuất tất cả các khoảng trắng, bao gồm cả dòng mới và trình phân tích cú pháp không phải lo lắng về điều đó.

Mặt khác, một khi bạn bắt đầu muốn nói với trình phân tích cú pháp về khoảng trắng, thì không khó để tạo dấu chấm phẩy tùy chọn. Bạn thường có thể gộp chúng lại với nhau bằng whitespacemã thông báo và trình phân tích cú pháp của bạn có thể xử lý tốt.

Ví dụ: thử chèn dấu chấm phẩy vào chuỗi câu lệnh C sau đây.

functionCall(3, 4) 9 + (3 / 8) variable++ while(1) { printf("Hello, world\n") }

Mặc dù có một số điều kỳ lạ mà bạn không còn có thể làm được, như while(1);, đối với hầu hết các phần, việc tương đối dễ dàng với các kỹ thuật phân tích cú pháp hiện đại để xác định nơi các câu lệnh kết thúc mà không có một dấu phân cách cụ thể. Ngay cả khi bạn vẫn muốn cho phép những thứ kỳ lạ, không khó để tạo ra một newline_or_semicolonthiết bị đầu cuối.


Khi C ban đầu được phát triển vào đầu những năm 1970, các bộ kết thúc câu lệnh là cần thiết để đơn giản hóa trình biên dịch. Vào giữa những năm 90, khi Javascript được phát triển, nó ít được quan tâm hơn.
Sean McS Something 8/10/2016

3

Dấu chấm phẩy rất hữu ích trong một ngữ pháp vì 2 lý do. Đầu tiên, nó cho phép bạn chia các câu lệnh dài thành nhiều dòng mà không có các ký tự tiếp tục hợp pháp (tôi đang nói về bạn, Fortran và Basic). Thứ hai, nó cho phép trình phân tích cú pháp có cách "từ bỏ" phân tích cú pháp khi cú pháp thực sự bị lỗi do lỗi chính tả. Ăn cắp từ ví dụ của Karl Bielefeldt,

functionCall(3, 4) 9 + (3 / 8) variable++ while(1) { printf("Hello, world\n") }

hãy tưởng tượng bạn đã gõ thêm một paren mở:

functionCall((3, 4) 9 + (3 / 8) variable++ while(1) { printf("Hello, world\n") }

bây giờ lỗi ở đâu? Nếu bạn đã có dấu chấm phẩy, trình phân tích cú pháp sẽ dễ dàng hơn khi bỏ dấu chấm phẩy đầu tiên. Nó thậm chí có thể tiếp tục phân tích cú pháp sau dấu chấm phẩy nếu muốn.

functionCall((3, 4);  <- something is wrong here. emit error and keep going.
                      9 + (3 / 8); variable++; while(1) { printf("Hello, world\n"); }

Bây giờ, trình phân tích cú pháp báo cáo lỗi dễ dàng hơn và dễ dàng xác định vị trí dòng / cột nơi xảy ra.


1
Fortran và Basic ít nhất đã chọn các dấu tiếp tục dòng (và và _, tương ứng). Đối với sheer "" OMG, họ đã nghĩ gì ", không có gì vượt qua FoxPro. Để tiếp tục một dòng, bạn đã sử dụng dấu chấm phẩy.
DougM

2

Dấu chấm phẩy không phải lúc nào cũng là tất cả hoặc không có gì giống như bạn đề cập trong câu hỏi của bạn. Ví dụ, ngữ pháp của Lua được thiết kế cẩn thận ở dạng tự do (tất cả các khoảng trắng, bao gồm cả dòng mới, có thể bị bỏ qua) nhưng cũng không cần sử dụng bất kỳ dấu chấm phẩy nào. Ví dụ: các chương trình sau là tương đương:

--One statement per line
x = 1
y = 2

--Multiple statements per line
x = 1 y = 2

--You can add semicolons if you want but its just for clarity:
x = 1; y = 2

0

Tất cả các thiết kế và xây dựng sang một bên, tôi tin rằng rất nhiều lập trình viên đến từ các nền tảng khác nhau và một số người đã học cách sử dụng dấu chấm phẩy và một số thì không. Rất nhiều ngôn ngữ mới hơn đang nổi lên không yêu cầu dấu chấm phẩy nhưng vẫn cho phép nó tồn tại. Tôi nghĩ rằng nó có thể chỉ là một cách để nhiều lập trình viên học cách viết mã bằng các ngôn ngữ mới này mà không phải từ bỏ thói quen của họ từ khi họ bắt đầu.

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.