11

Nó khá rõ ràng lý do tại sao một ngôn ngữ lập trình chức năng mà muốn được lười biếng cần phải được tinh khiết. Tôi đang nhìn vào câu hỏi ngược lại: nếu một ngôn ngữ muốn trở nên tinh khiết, liệu có một lợi thế lớn trong việc lười biếng? Một lập luận, được thực hiện bởi một trong những nhà thiết kế của Haskell, là nó loại bỏ sự cám dỗ; có lẽ, nhưng tôi đang cố gắng cân nhắc những lợi thế cụ thể hơn.Việc sử dụng thực tế cho sự lười biếng như một tính năng ngôn ngữ được tích hợp là gì?

Giả sử bạn muốn lập trình chức năng, trường hợp sử dụng khi nào tính năng lười biếng tích hợp cho phép bạn thể hiện rõ ràng hơn, đơn giản hoặc chính xác?

Nói một cách đơn giản: Tại sao sự lười biếng lại quan trọng đến nỗi bạn muốn xây dựng nó thành ngôn ngữ?

(Tôi đang tìm trường hợp sử dụng hướng tới ứng dụng hơn là bản trình diễn - Tôi biết bạn có thể làm những việc như tạo danh sách vô hạn số nguyên tố bằng cách lọc danh sách vô hạn các số tự nhiên. viết rằng gấp mười lần 'fore ăn trưa ...)

+0

Đây là một chủ đề thú vị, nhưng bạn đang yêu cầu nó một cách khá đáng tiếc, về cơ bản yêu cầu một grabbag của bất kỳ kịch bản mà ai đó có thể tưởng tượng đánh giá lười biếng là hữu ích. Nếu bạn đang thiết kế một ngôn ngữ, bạn sẽ làm tốt để tập trung vào các quyết định cụ thể mà bạn đang cố gắng thực hiện và yêu cầu hỗ trợ cân nhắc các tùy chọn để bạn có thể đưa ra lựa chọn sáng suốt. – Shog9

+0

Tôi không biết nếu bạn đang đi để có được câu trả lời tốt ở đây, câu hỏi này là nhiều hơn cho các nhà thiết kế ngôn ngữ lập trình hơn cho các lập trình viên. Đó là loại câu hỏi mà một [trang web về khoa học máy tính] (http://area51.stackexchange.com/proposals/35636/computer-science-non-programming?referrer=4M74nqLafvszXN85c5ibxQ2) sẽ hoạt động tốt hơn cho. Tôi khuyên bạn nên các bài viết [trích dẫn trên Wikipedia] (http://en.wikipedia.org/wiki/Lazy_evaluation#Further_reading) (không phải là bài viết WP chính nó), đặc biệt là "Tại sao FP vấn đề". – Gilles

+0

rwallace: Dựa trên chỉnh sửa @Gilles, tôi đã sửa đổi thêm để nhấn mạnh sự lười biếng câu hỏi như một tính năng tích hợp (với các ví dụ được sử dụng để minh họa thay vì ví dụ như mục tiêu cuối cùng) và mở lại với giả định rằng điều này là chấp nhận được. Nếu bạn không đồng ý, hãy thảo luận. – Shog9

Trả lời

19

"Không có gì được đánh giá cho đến khi cần ở nơi khác" là phép ẩn dụ đơn giản không bao gồm tất cả các khía cạnh của đánh giá lười biếng (ví dụ: nó không đề cập đến hiện tượng nghiêm ngặt).

Từ quan điểm lý thuyết, có 3 cách để đi khi thiết kế một ngôn ngữ thuần túy (tất nhiên nếu nó dựa trên một số loại tính toán lambda và không phải trên các mô hình đánh giá kỳ lạ hơn): nghiêm ngặt, không nghiêm ngặt và tổng số.

Mỗi người trong số họ có những ưu điểm và nhược điểm của nó, vì vậy bạn cần đọc các tài liệu nghiên cứu tương ứng.

Tổng số ngôn ngữ thuần túy nhất trong ba ngôn ngữ đó. Trong hai trường hợp khác, việc không chấm dứt có thể được xem như là một tác dụng phụ, vì vậy các máy phân tích toàn diện và nghiêm ngặt phải được xây dựng để duy trì hiệu quả thực hiện. Cả hai phân tích đều không thể xác định được, vì vậy các máy phân tích không bao giờ có thể hoàn thành.

Tuy nhiên, tổng số ngôn ngữ ít biểu cảm nhất: không thể hoàn thành toàn bộ ngôn ngữ. Một cách tiếp cận thường xuyên để có được sự biểu cảm đủ tốt là có một hệ thống chứng minh tích hợp cho đệ quy tốt, không dễ xây dựng hơn các máy phân tích cho các ngôn ngữ không phải là tổng số.

Từ quan điểm thực tế, ngữ nghĩa không nghiêm ngặt cho phép bạn dễ dàng xác định các điều khiển trừu tượng hơn, vì cấu trúc điều khiển về cơ bản không nghiêm ngặt. Trong một ngôn ngữ nghiêm ngặt, bạn vẫn cần một số nơi có ngữ nghĩa không nghiêm ngặt. Ví dụ. Cấu trúc if có ngữ nghĩa không nghiêm ngặt ngay cả trong các ngôn ngữ nghiêm ngặt.

Vì vậy, nếu ngôn ngữ của bạn là nghiêm ngặt, cấu trúc điều khiển là trường hợp đặc biệt. Ngược lại, một ngôn ngữ không nghiêm ngặt có thể được thống nhất không nghiêm ngặt - nó không có nhu cầu vốn có trong cấu trúc nghiêm ngặt.

Đối với "người viết bữa trưa trước mười lần" - bất kỳ ai sử dụng Haskell cho dự án của họ đều làm. Tôi nghĩ rằng việc phát triển một dự án phi đồ chơi bằng một ngôn ngữ (một ngôn ngữ không nghiêm ngặt trong trường hợp của bạn) là cách tốt nhất để nắm bắt những ưu điểm và nhược điểm của nó.

Dưới đây là một vài usecases chung cho sự lười biếng minh họa bằng ví dụ phi đồ chơi:

  1. trường hợp khi kiểm soát dòng chảy là khó dự đoán. Hãy suy nghĩ về ngữ pháp thuộc tính khi không có sự lười biếng, bạn phải thực hiện một kiểu topo trên các thuộc tính để giải quyết các dependensies. Sắp xếp lại mã của bạn mỗi lần biểu đồ phụ thuộc được thay đổi là không thực tế. Trong Haskell bạn có thể thực hiện các hình thức ngữ pháp thuộc tính mà không cần phân loại rõ ràng và có ít nhất hai triển khai thực tế trên Hackage. Các ngữ pháp thuộc tính có ứng dụng rộng trong xây dựng trình biên dịch.

  2. Cách tiếp cận "tạo và tìm kiếm" để giải quyết nhiều vấn đề về optimizaton. Trong một ngôn ngữ nghiêm ngặt, bạn phải xen kẽ thế hệ và tìm kiếm, trong Haskell bạn chỉ soạn các hàm tạo và tìm kiếm riêng biệt, và mã của bạn vẫn còn mô-đun theo cú pháp, nhưng xen kẽ khi chạy. Hãy suy nghĩ về vấn đề người bán hàng đi du lịch (TSP), khi bạn tạo ra tất cả các chuyến tham quan có thể và sau đó tìm kiếm thông qua chúng bằng cách sử dụng một thuật toán nhánh và ràng buộc. Lưu ý rằng chi nhánh một thuật toán ràng buộc chỉ kiểm tra một số thành phố đầu tiên của một tour du lịch, chỉ có các phần cần thiết của các tuyến đường được tạo ra. TSP có một số ứng dụng ngay cả trong công thức tinh khiết nhất của nó, chẳng hạn như lập kế hoạch, hậu cần và sản xuất vi mạch. Hơi biến đổi, nó xuất hiện như là một vấn đề phụ trong nhiều lĩnh vực, chẳng hạn như trình tự DNA.

  3. Mã lười có luồng điều khiển phi mô-đun, do đó, một chức năng duy nhất có thể có nhiều luồng điều khiển có thể tùy thuộc vào môi trường mà nó thực thi. Hiện tượng này có thể được xem như một loại 'đa hình điều khiển luồng' trừu tượng dòng chảy là chung chung hơn so với các đối tác nghiêm ngặt của họ, và một thư viện chuẩn của các hàm bậc cao hơn hữu ích hơn nhiều trong một ngôn ngữ lười biếng. Hãy suy nghĩ về máy phát điện Python, vòng lặp và danh sách các trình lặp: trong các hàm danh sách Haskell bao gồm cả ba giai đoạn, với luồng điều khiển thích ứng với các kịch bản sử dụng khác nhau do sự lười biếng. Nó không giới hạn trong danh sách - nghĩ về Data.Arrow và iteratees, phiên bản lười biếng và nghiêm ngặt của State monad vv. Cũng lưu ý rằng luồng điều khiển không mô-đun vừa là một lợi thế và bất lợi, vì nó làm cho lý do về hiệu suất khó hơn.

  4. Cấu trúc dữ liệu vô hạn có thể hữu ích vượt quá các ví dụ về đồ chơi. Xem các tác phẩm của Conal Elliott về việc ghi nhớ các hàm bậc cao hơn bằng cách sử dụng các lần thử. Các cấu trúc dữ liệu vô hạn xuất hiện dưới dạng các khoảng trống tìm kiếm vô tận (xem 2), các vòng lặp vô hạn và các máy phát không bao giờ cạn kiệt theo nghĩa Python (xem 3).

+0

Nguồn của ẩn dụ được đề cập có vẻ là "Người đánh giá lười biếng" của Henderson và Morris, POPL'76 – nponeccop

2

Mac OS X của lõi ảnh là một ví dụ thực tiễn tốt của việc đánh giá lười biếng.

Về cơ bản, hình ảnh lõi cho phép bạn tạo biểu đồ theo chu kỳ trực tiếp của bộ tạo và bộ lọc hình ảnh. Không có đánh giá thực sự diễn ra cho đến bước cuối cùng trong quá trình: hiện thực hóa. Khi bạn yêu cầu thực hiện biểu đồ Hình ảnh cốt lõi, khung hình ảnh cuối cùng được truyền ngược qua các phép biến đổi của biểu đồ, do đó giảm thiểu số lượng giá trị pixel thực tế cần được đánh giá.

2

Có một cuộc thảo luận rộng rãi về điểm này trong cổ điển của Hughes Why Functional Programming Matters. Trong đó, Hughes lập luận rằng sự lười biếng cho phép cải thiện mô đun, bằng cách sử dụng một số ví dụ có thể truy cập.

Các vấn đề liên quan