Bài viết được liên kết chắc chắn hiểu đúng về Vòng lặp N + 1/2 của Donald Knuth . Thể hiện bằng C / C ++ / Java:
for (;;) {
get next element;
if (at the end) break;
process the element;
}
Điều này hữu ích để đọc các dòng hoặc ký tự từ một tệp, kiểm tra xem bạn đã đạt EOF chưa, và sau đó xử lý nó. Tôi đã quá quen với việc nhìn thấy mô hình for(;;)..if(..)break;
xuất hiện rằng nó là thành ngữ đối với tôi. (Trước khi tôi đọc bài báo Knuth, được in lại trong cuốn sách Lập trình văn học , bài này đã từng là "wtf?".)
Knuth đề xuất các từ khóa loop/while/repeat
:
loop:
S;
while C:
T;
repeat
Trường hợp S
và T
là chủ sở hữu vị trí cho một loạt các câu lệnh bằng 0 hoặc nhiều hơn và C
là một điều kiện boolean. Nếu không có S
câu lệnh thì đó sẽ là một vòng lặp while và nếu không có T
câu lệnh thì đó sẽ là một vòng lặp do.
Bản thân cấu trúc này có thể được khái quát bằng cách cho phép không hoặc nhiều while C
mệnh đề, làm cho nó hoàn hảo để thể hiện các vòng lặp vô hạn và sau đó một số điều kiện hiếm hơn sẽ cần hai kiểm tra.
Trong cùng một bài viết, Knuth đã đề xuất một cơ chế báo hiệu sẽ là một phiên bản cục bộ của các trường hợp ném / bắt ngoại lệ (như là một cách thay thế cho việc sử dụng goto).
Cho tôi? Tôi muốn Java hỗ trợ tối ưu hóa cuộc gọi đuôi, để tôi có thể diễn đạt bất kỳ cấu trúc điều khiển chung nào khi cần.
Cập nhật: Tôi quên đề cập rằng nhiều lập trình viên C / C ++ / Java đã khắc phục điều này bằng cách sử dụng một bài tập được nhúng trong điều kiện while
:
while ((c = getc(f)) != -1) {
T;
}
Sử dụng các thuật ngữ từ cấu trúc của Knuth, điều này được phép khi S
và C
có thể được kết hợp thành một biểu thức. Một số người ghét nhìn thấy bài tập được nhúng ở trên, trong khi những người khác ghét nhìn thấy phần break
ở for (;;)
trên. Nhưng khi S
và C
không thể được kết hợp, chẳng hạn như khi S
có nhiều câu lệnh, thì câu lệnh for (;;)
thay thế duy nhất mà không lặp lại mã. Cách khác là đơn giản là sao chép S
mã:
S;
while (C) {
T;
S;
}
Sự loop/while/repeat
thay thế của Knuth có vẻ tốt hơn nhiều.