Algol 60
Đây là một boolean procedure
câu hỏi mà câu hỏi yêu cầu (lưu ý: Algol 60 được định nghĩa theo danh sách các mã thông báo mà không sửa cú pháp cho chúng, bên dưới sử dụng cú pháp Marst để thể hiện các mã thông báo riêng lẻ tạo nên chương trình):
boolean procedure recursion detector(n);
boolean n;
begin
own boolean nested, seen nested;
boolean was nested, retval;
was nested := nested;
begin if nested then seen nested := true end;
nested := true;
retval := n; comment "for the side effects, we ignore the result";
nested := was nested;
retval := seen nested;
begin if ! nested then seen nested := false end;
recursion detector := retval
end;
xác minh
Đây là mã kiểm tra tôi đã sử dụng:
procedure outboolean(c, b);
integer c;
boolean b;
begin
if b then outstring(c, "true\n") else outstring(c, "false\n")
end;
begin
outboolean(1, recursion detector(false));
outboolean(1, recursion detector(true));
outboolean(1, recursion detector(recursion detector(false)));
outboolean(1, recursion detector(false | recursion detector(true)));
outboolean(1, recursion detector(false & recursion detector(true)));
outboolean(1, recursion detector(recursion detector(recursion detector(false))))
end
Theo dự kiến, đầu ra là:
false
false
true
true
true comment "because & does not short-circuit in Algol 60";
true
Giải trình
Algol 60 có thứ tự đánh giá khác với hầu hết các ngôn ngữ, có logic riêng, và thực sự mạnh mẽ và tổng quát hơn nhiều so với thứ tự đánh giá thông thường, nhưng khá khó để con người có thể hiểu được (và cũng khá khó đối với máy tính để thực hiện hiệu quả, đó là lý do tại sao nó đã được thay đổi cho Algol 68). Điều này cho phép một giải pháp không có sự gian lận (chương trình không cần nhìn vào cây phân tích hoặc bất cứ thứ gì tương tự, và không giống như hầu hết các giải pháp khác ở đây, điều này sẽ hoạt động tốt nếu cuộc gọi lồng nhau được thực hiện thông qua một FFI).
Tôi cũng quyết định thể hiện một vài điều kỳ quặc khác của ngôn ngữ. (Đáng chú ý, tên biến có thể chứa khoảng trắng; điều này khá hữu ích cho khả năng đọc, vì chúng không thể chứa dấu gạch dưới. Tôi cũng thích thực tế rằng chỉ báo nhận xét là từ theo nghĩa đen comment
trong hầu hết các mã hóa cú pháp. Algol 68 thấy điều này khá khó xử. bình luận và được giới thiệu ¢
như một cách thay thế. Các trích dẫn xung quanh phần bình luận không cần thiết, tôi chỉ cần thêm chúng cho rõ ràng và để ngăn bình luận vô tình kết thúc khi tôi gõ một dấu chấm phẩy.) Tôi thực sự thích các khái niệm rộng của ngôn ngữ (nếu không phải là chi tiết), nhưng thật dài dòng đến nỗi tôi hiếm khi sử dụng nó trên PPCG.
Cách chính mà Algol 60 khác với các ngôn ngữ mà nó truyền cảm hứng (như Algol 68 và gián tiếp C, Java, v.v., những người biết K & R C có thể sẽ nhận ra cú pháp này cho các hàm) là một đối số hàm được xử lý hơi giống một chút lambda của riêng mình; ví dụ: nếu bạn đưa đối số 5
cho hàm chỉ là số 5, nhưng nếu bạn đưa ra đối số đó, x+1
bạn sẽ nhận được chính xác những gì bạn đã chỉ định, khái niệm " x
cộng 1", thay vì kết quả của x
cộng 1. Sự khác biệt ở đây là nếu x
thay đổi, sau đó cố gắng đánh giá đối số chức năng trong câu hỏi sẽ thấy giá trị mới củax
. Nếu một đối số hàm không được đánh giá bên trong hàm, thì nó cũng sẽ không được đánh giá bên ngoài hàm; tương tự, nếu nó được đánh giá nhiều lần trong hàm, nó sẽ được đánh giá riêng mỗi lần (giả sử rằng điều này không thể được tối ưu hóa). Điều này có nghĩa là có thể thực hiện những việc như nắm bắt chức năng của, nói if
hoặc while
trong một chức năng.
Trong chương trình này, chúng tôi khai thác thực tế là nếu một lệnh gọi hàm xuất hiện trong một đối số cho hàm đó, điều đó có nghĩa là hàm sẽ chạy đệ quy (vì đối số được đánh giá tại điểm hoặc điểm mà hàm đánh giá chính xác , không sớm hơn hoặc muộn hơn, và điều này nhất thiết phải nằm trong cơ thể chức năng). Điều này làm giảm vấn đề phát hiện nếu chức năng đang chạy đệ quy, dễ dàng hơn nhiều; tất cả những gì bạn cần là một biến cục bộ luồng cảm nhận nếu có một cuộc gọi đệ quy (cộng với, trong trường hợp này, một cuộc gọi khác để truyền thông tin ngược lại theo cách khác). Chúng ta có thể sử dụng một biến tĩnh (nghĩa làown
) cho mục đích này, vì Algol 60 là đơn luồng. Tất cả những gì chúng ta phải làm sau đó là đưa mọi thứ trở lại như cũ, để chức năng sẽ hoạt động chính xác nếu được gọi nhiều lần (theo yêu cầu của quy tắc PPCG).
Hàm không trả về giá trị mong muốn từ các cuộc gọi bên trong tại thời điểm này (ít nhất là nếu bạn cho rằng họ nên tìm kiếm các cuộc gọi tự chỉ trong các đối số của mình , thay vì tự đếm); làm cho công việc đó khá dễ dàng bằng cách sử dụng các nguyên tắc chung tương tự, nhưng phức tạp hơn và sẽ che khuất hoạt động của chức năng. Nếu điều đó được coi là cần thiết để tuân thủ câu hỏi, thì không quá khó để thay đổi.
print(func(), func(func()))
, hay sẽ chỉ có một cuộc gọi cấp cao nhất đến chức năng ngay sau khi nó được xác định?