2009-03-16 28 views
6

Có vẻ như có rất nhiều ví dụ về những điều thông minh được thực hiện bằng ngôn ngữ được đánh giá lười biếng mà không thể thực hiện được trong môi trường có đánh giá nghiêm ngặt. Ví dụ: danh sách vô hạn trong Haskell hoặc replacing every element in a tree with the tree's minimum value in one pass.Sử dụng thông minh đánh giá chặt chẽ ở đâu?

Có bất kỳ ví dụ về những điều thông minh được thực hiện bằng ngôn ngữ được đánh giá nghiêm ngặt không thể dễ dàng thực hiện bằng ngôn ngữ được đánh giá lười biếng không?

+1

Lý thuyết sang một bên, có thể sử dụng thông minh đánh giá nghiêm ngặt trong các ngôn ngữ lười biếng. Haskell có "!" nghiêm ngặt chú thích cho datatypes để sử dụng trong buộc đánh giá các điều khoản mà lười biếng sẽ chỉ có gây ra sưng lên bộ nhớ. Các ví dụ hay về thời điểm tắt lười biếng chắc chắn sẽ là "sử dụng thông minh về đánh giá nghiêm ngặt". – rndmcnlly

Trả lời

4

Vâng, không, nhiều hơn hoặc ít hơn theo định nghĩa. Trong ngôn ngữ đánh giá lười biếng, bạn nên theo định nghĩa nhận được kết quả tương tự mà bạn nhận được với mạnh mẽ (là những người thực sự sử dụng đánh giá "nghiêm ngặt" ngay bây giờ?), ngoại trừ để trì hoãn đánh giá cho đến khi cần thiết. tất cả. Vì vậy, nếu bạn có thể nhận được một số hành vi khác nhau ngoại trừ cho điều đó, nó sẽ là một lỗi.

+1

Trên thực tế, sự lười biếng có ngữ nghĩa hơi khác với độ nghiêm ngặt. Ví dụ trong một ngôn ngữ nghiêm ngặt "const 1 undefined" là không xác định, nhưng trong một ngôn ngữ lười biếng nó đánh giá đến 1. Lý do là một ngôn ngữ nghiêm ngặt đánh giá "không xác định", nhưng một ngôn ngữ lười biếng không. –

0

Trong ngôn ngữ đánh giá nghiêm ngặt như C#, bạn có thể đạt được đánh giá lười biếng bằng cách trả lại một phần nhỏ cho một giá trị (Func) thay vì giá trị của chính nó. Như một ví dụ trong việc xây dựng các Y-Combinator trong C# có thể được thực hiện theo cách này:

public Func<int, int> Y(Func<Func<int, int>, Func<int, int>> f) 
{ 
    return x => f(Y(f))(x); 
} 

khai này sẽ ngắn gọn hơn trong một môi trường lười biếng:

Y f = f (Y f) 
+0

Điều này không áp dụng cho ví dụ Y-Combinator của bạn, nhưng như một lưu ý: Để nhận được đánh giá theo nhu cầu (như trong Haskell) trong C#, bạn nên sử dụng 'Lazy ', chứ không phải' Func ' (sau này sẽ tính lại giá trị mỗi khi nó được sử dụng). – FunctorSalad

0

như Charlie Martinwrote, kết quả của chương trình nghiêm ngặt và lười biếng nên tương đương. Sự khác biệt nằm trong thời gian và không gian hạn chế và/hoặc ngôn ngữ biểu cảm. Bên cạnh hiệu quả hoạt động của sự lười biếng đối với các giá trị không cần thiết, người ta có thể dễ dàng giới thiệu các cấu trúc ngôn ngữ mới mà không có khái niệm ngôn ngữ bổ sung (ví dụ: macro trong LISP). Dù sao đi nữa, sự lười biếng có thể làm bạn khó khăn How does Haskell tail recursion work? và suy nghĩ tương tự có thể phức tạp hơn ngôn ngữ nghiêm ngặt. (Không nên Haskell biên dịch nhận ra rằng tính toán +1 là ít tốn kém hơn so với làm thunk (x + 1)?)

0

Tôi chương trình trong Erlang một chút, và tìm ra thiếu thẩm lười biếng mà tôi đã học lại tại trường đại học khá bực bội.

Tôi đã xem xét một thời gian ngắn tại một số vấn đề về dự án Euler, đặc biệt là các vấn đề liên quan đến số nguyên tố.

Với đánh giá lười biếng, bạn có thể có hàm trả về danh sách tất cả số nguyên tố, nhưng nó chỉ thực sự trả về những số mà bạn thực sự muốn. Do đó, thật dễ dàng để nói "hãy cho tôi số nguyên tố đầu tiên n".

Không có đánh giá lười biếng, bạn có xu hướng kết thúc với một hạn chế hơn "cung cấp cho tôi danh sách tất cả các số nguyên tố từ 1 đến n".

5

Không; có một số điều bạn có thể làm * với đánh giá lười biếng (giảm mức bình thường của AKA hoặc giảm ngoài cùng bên trái) mà bạn không thể thực hiện với việc đánh giá nghiêm ngặt, nhưng không thể thực hiện theo cách khác.

Lý do cho điều này là đánh giá lười biếng là một cách nào đó 'nhất chung' cách để đánh giá, mà được gọi là:

Các tính toán Adequacy lý: Nếu một số thứ tự của đánh giá chấm dứt và tạo ra một kết quả cụ thể, sau đó đánh giá lười biếng cũng sẽ chấm dứt và sản xuất cùng một kết quả.

* (xin lưu ý rằng chúng tôi đang không nói về Turing-tương đương ở đây)

+0

Mặc dù được đánh giá là câu trả lời hay nhất, tuyên bố của bạn là sai, hãy xem câu trả lời của tôi bên dưới. – Ingo

8

Những điều chính bạn có thể làm một cách dễ dàng bằng một ngôn ngữ háo hức (chặt chẽ) chứ không phải bằng một ngôn ngữ lười biếng:

  • Dự đoán từ mã nguồn thời gian và không gian chi phí của chương trình của bạn

  • tác dụng phụ Giấy phép, trong đó có hằng số thời gian upda te của các mảng có thể thay đổi, giúp dễ dàng triển khai một số thuật toán nhanh hơn

Theo tôi, lợi ích chính của ngôn ngữ háo hức là dễ dàng hơn để mã của bạn thực hiện theo cách bạn muốn và ở đó là rất ít bẫy hiệu suất trong đó một thay đổi nhỏ trong mã dẫn đến thay đổi lớn về hiệu suất.

Có nói rằng, trên toàn bộ tôi thích viết những thứ phức tạp trong Haskell.

-5

Câu trả lời được đánh giá là tốt nhất, không may là do lỗi logic. Từ định lý Porges trích dẫn không tuân theo một trong những có thể làm nhiều hơn trong một ngôn ngữ lười biếng. Bằng chứng ngược lại là tất cả các chương trình bằng ngôn ngữ lười được biên dịch thành các ngôn ngữ nghiêm ngặt (được biên dịch sâu hơn cho các chương trình lắp ráp) hoặc được thực hiện bởi một thông dịch viên viết bằng ngôn ngữ nghiêm ngặt (và có, thông dịch viên một chương trình lắp ráp tối ưu).

+0

Đây là Turing tương đương ... Người hỏi hỏi nếu có bất kỳ 'thủ thuật gọn gàng' có thể được thực hiện với một ngôn ngữ nghiêm ngặt mà không thể được thực hiện với một lười biếng; định lý đó nói không, bởi vì đánh giá lười biếng là thứ tự eval tổng quát nhất. (Nếu chúng ta nhìn vào điều này chỉ từ một POV trật tự giảm.) – porges

+0

Tôi đồng ý, tất nhiên, nhưng bạn đã nói "rằng có một số điều bạn có thể làm * với đánh giá lười biếng ... mà bạn không thể làm với đánh giá nghiêm ngặt ". Mà vẫn còn sai. Tất nhiên, bằng cách sử dụng một danh sách lười biếng là dễ dàng hơn, nói, Haskell hơn trong Java, nhưng đây không phải là câu hỏi. – Ingo

2

Cách sử dụng laziness rõ ràng nhất trong ngôn ngữ hàng ngày là câu lệnh "if", trong đó chỉ có một nhánh của điều kiện được thực thi.

Ngược lại với ngôn ngữ hoàn toàn không nghiêm ngặt (lười biếng) sẽ là một ngôn ngữ hoàn toàn nghiêm ngặt.

Có ít nhất một trường hợp 'hoàn toàn nghiêm ngặt' có lợi, cụ thể là branch predication.

diễn giải Rough của bài viết liên quan:

Cách đây rất lâu trong thế giới của CPU, hướng dẫn để thực hiện được nạp khi điều kiện chi nhánh đã được thử nghiệm. Tại một số điểm, đường ống dẫn đã được thêm vào để giảm thời gian tải. Nhược điểm là một CPU sẽ không biết chi nhánh nào cần tải, vì vậy nó sẽ mặc định tải một nhánh. Nếu nhánh rẽ theo cách khác, đường ống sẽ dừng lại trong khi mã cho nhánh kia đã được nạp.

Giải pháp là tải cả hai nhánh, thực hiện cả hai nhánh, sau đó kết quả của điều kiện cho bạn biết kết quả nhánh nào sẽ giữ lại, và cái nào cần vứt bỏ. Sau đó, bạn không nhận được các quầy hàng đường ống.

Đây là ví dụ yêu thích của tôi (chỉ?) Về lợi ích của một ngôn ngữ hoàn toàn nghiêm ngặt.

1

Các chương trình 'Xin chào, Thế giới' đến với tâm trí, hoặc tất cả mọi thứ liên quan đến tác dụng phụ về cơ bản. Trong đánh giá nghiêm ngặt, việc đánh giá một biểu thức có thể dễ dàng có tác dụng phụ khi bạn có một cái nhìn tổng quan rõ ràng về thứ tự đánh giá, và do đó thứ tự của các tác dụng phụ, thường quan trọng trong các tác dụng phụ. Đó là lợi thế cơ bản của việc đánh giá nghiêm ngặt, và cũng là lý do tại sao hầu hết các ngôn ngữ đều có nó. Và tại sao ngay cả các ngôn ngữ định hướng hiệu suất như C thường sử dụng mô hình truyền theo giá trị. Cả hai có thể làm tương tự, chỉ với các mức độ khó khác nhau của con người, bạn hoàn toàn có thể mô phỏng danh sách vô hạn bằng một ngôn ngữ nghiêm ngặt, và bạn có thể mô phỏng tất cả các hiệu ứng của các tác dụng phụ với ngôn ngữ không nghiêm ngặt.

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