Các tiếp tục hạng nhất có hữu ích trong các ngôn ngữ lập trình hướng đối tượng hiện đại không?


10

Continuations cực kỳ hữu ích trong các ngôn ngữ lập trình chức năng (ví dụ: Contđơn nguyên trong Haskell) vì chúng cho phép ký hiệu đơn giản và thường xuyên cho mã kiểu bắt buộc. Chúng cũng hữu ích trong một số ngôn ngữ mệnh lệnh cũ hơn vì chúng có thể được sử dụng để triển khai các tính năng ngôn ngữ bị thiếu (ví dụ: ngoại lệ, coroutines, chủ đề màu xanh lá cây). Nhưng đối với một ngôn ngữ hướng đối tượng hiện đại có hỗ trợ tích hợp cho các tính năng này, sẽ có những đối số nào để thêm hỗ trợ cho các phần tiếp theo hạng nhất (cho dù kiểu cách phân cách hiện đại hơn resetshiftgiống như lược đồ call-with-current-continuation)?

Có tranh luận chống lại việc thêm hỗ trợ ngoài hiệu suất và độ phức tạp của việc thực hiện không?

Câu trả lời:


15

Hãy để Eric Lippert trả lời câu hỏi này:

Câu hỏi rõ ràng vào thời điểm này là: nếu CPS tuyệt vời như vậy thì tại sao chúng ta không sử dụng nó mọi lúc? Tại sao hầu hết các nhà phát triển chuyên nghiệp không bao giờ nghe nói về nó, hoặc, những người có, nghĩ về nó như một điều mà chỉ những lập trình viên Scheme điên rồ mới làm?

Trước hết, hầu hết mọi người thường nghĩ về các chương trình con, vòng lặp, thử-bắt-cuối và v.v ... là lý do về các đại biểu được sử dụng cho luồng điều khiển theo cách này. Tôi đang xem xét các ghi chú của mình về CPS từ CS442 ngay bây giờ và tôi thấy rằng vào năm 1995, tôi đã viết ra một câu hỏi: Trả lời với các phần tiếp theo, bạn phải đứng trên đầu và kéo mình ra bên ngoài. Giáo sư Duggan (*) hoàn toàn chính xác khi nói điều đó. Nhớ lại từ một vài ngày trước rằng ví dụ nhỏ bé của chúng ta về phép biến đổi CPS của biểu thức C # M (B ()? C (): D ()) liên quan đến bốn lambdas. Không phải ai cũng giỏi đọc mã sử dụng các hàm bậc cao hơn. Nó áp đặt một gánh nặng nhận thức lớn.

Hơn nữa: một trong những điều hay về việc có các câu lệnh luồng điều khiển cụ thể được đưa vào ngôn ngữ là chúng cho phép mã của bạn thể hiện rõ ràng ý nghĩa của luồng điều khiển trong khi ẩn các cơ chế - ngăn xếp cuộc gọi và trả về địa chỉ và danh sách xử lý ngoại lệ và các vùng được bảo vệ và như thế. Sự liên tục làm cho các cơ chế của dòng điều khiển rõ ràng trong cấu trúc của mã. Tất cả sự nhấn mạnh vào cơ chế có thể lấn át ý nghĩa của mã.

Trong bài viết tiếp theo , ông giải thích cách thức không đồng bộ và liên tục hoàn toàn tương đương với nhau và trình diễn một hoạt động mạng đồng bộ đơn giản (nhưng chặn) và viết lại theo kiểu không đồng bộ, đảm bảo che giấu tất cả các ẩn gotchas phải được bảo hiểm để làm cho đúng. Nó biến thành một đồ sộ mớ hỗn độn của mã. Tóm tắt của anh ấy ở cuối:

Chúa ơi, thật là một mớ hỗn độn đáng tin. Chúng tôi đã mở rộng hai dòng mã hoàn toàn rõ ràng thành hai chục dòng mì spaghetti tuyệt vời nhất bạn từng thấy. Và tất nhiên nó vẫn không biên dịch được vì các nhãn không nằm trong phạm vi và chúng tôi có lỗi gán rõ ràng. Chúng tôi vẫn cần viết lại mã để khắc phục những vấn đề đó.

Hãy nhớ những gì tôi đã nói về ưu và nhược điểm của CPS?

  • PRO: Các luồng điều khiển phức tạp và thú vị có thể được xây dựng từ các phần đơn giản - kiểm tra.
  • CON: Việc thống nhất hóa dòng điều khiển thông qua các phần tiếp theo là khó đọc và khó lý luận về - kiểm tra.
  • CON: Mã đại diện cho các cơ chế của luồng điều khiển hoàn toàn áp đảo ý nghĩa của mã - kiểm tra.
  • CON: Việc chuyển đổi luồng điều khiển mã thông thường thành CPS là loại điều mà trình biên dịch giỏi, và hầu như không có ai khác - kiểm tra.

Đây không phải là một số bài tập trí tuệ. Những người thực sự cuối cùng viết mã tương đương với đạo đức mọi lúc khi họ đối phó với sự không đồng bộ. Và, trớ trêu thay, ngay cả khi các bộ xử lý đã nhanh hơn và rẻ hơn, chúng ta dành nhiều thời gian hơn để chờ đợi những thứ không bị ràng buộc bởi bộ xử lý. Trong nhiều chương trình, phần lớn thời gian dành cho bộ xử lý được chốt ở mức 0 để chờ các gói mạng thực hiện chuyến đi từ Anh đến Nhật Bản và quay lại hoặc để đĩa quay, hoặc bất cứ điều gì.

Và tôi thậm chí không nói về những gì sẽ xảy ra nếu bạn muốn sáng tác các hoạt động không đồng bộ hơn nữa. Giả sử bạn muốn biến ArchiveDocument thành một hoạt động không đồng bộ cần có một đại biểu. Bây giờ tất cả các mã gọi nó cũng phải được viết bằng CPS. Những vết nhơ chỉ lan ra.

Nhận được logic không đồng bộ là rất quan trọng, nó sẽ chỉ quan trọng hơn trong tương lai, và các công cụ chúng tôi đã cung cấp cho bạn khiến bạn đứng trên đầu và biến mình ra bên ngoài như lời giáo sư Duggan nói một cách khôn ngoan.

Phong cách tiếp tục là mạnh mẽ, vâng, nhưng phải có một cách tốt hơn để sử dụng tốt sức mạnh đó hơn là mã ở trên.

Cả hai bài viết và loạt bài sau về tính năng ngôn ngữ C # mới chuyển tất cả mớ hỗn độn này vào trình biên dịch và cho phép bạn viết mã dưới dạng luồng điều khiển bình thường với một từ khóa đặc biệt để đánh dấu các phần nhất định là không đồng bộ, rất đáng đọc ngay cả khi bạn ' không phải là nhà phát triển C #. Tôi không, nhưng đó vẫn là trải nghiệm khai sáng khi tôi chạy qua nó lần đầu tiên.


4
Nó đáng chú ý là nếu hỗ trợ ngôn ngữ của bạn cú pháp mở rộng như macro, continuations sau đó trở thành xa hữu ích hơn vì bạn có thể che giấu các cơ chế để thực hiện các loại dòng điều khiển thú vị bên trong các phần mở rộng cú pháp. Về cơ bản, đó là cách "chờ" hoạt động, nó chỉ được định nghĩa bằng ngôn ngữ vì C # không cung cấp các công cụ để tự xác định các loại tiện ích mở rộng cú pháp đó.
Jack

Bài viết hay, mặc dù tôi sẽ lưu ý rằng CPS và các phần tiếp theo hạng nhất không giống nhau một cách chính xác (CPS là những gì bạn làm trong một ngôn ngữ không hỗ trợ cho các phần tiếp theo khi bạn thấy bạn cần chúng). Có vẻ như C # đang đi xuống chính xác cùng một tuyến đường mà tôi đang nghĩ đến (mặc dù tôi không thể quyết định liệu tôi có muốn tự động hóa chuyển đổi lốp thành CPS hay thực hiện các phần tiếp theo được phân tách sao chép toàn bộ ngăn xếp).
Jules

@Jack - đó chính xác là những gì tôi đang xem xét ngay bây giờ: ngôn ngữ tôi đang thiết kế có một cơ sở vĩ mô có thể hỗ trợ chuyển đổi CPS tự động. Nhưng các phần tiếp theo bản địa đầy đủ có thể cho hiệu suất tốt hơn ... câu hỏi là, chúng có thường được sử dụng trong tình huống quan trọng về hiệu suất không?
Jules
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.