2012-01-10 22 views
6

Trong hầu hết các ngôn ngữ lập trình, các đối số được truyền cho hàm được đánh giá trước khi chức năng sử dụng chúng, tức là chúng được đánh giá háo hức.Tại sao hầu hết các ngôn ngữ lập trình sử dụng đánh giá háo hức cho các đối số được truyền cho một hàm?

Với tôi, có vẻ như sẽ có ý nghĩa hơn nhiều khi đánh giá các đối số chỉ khi chức năng sử dụng chúng, tức là, uể oải. Điều này có ý nghĩa hơn với tôi bởi vì nó có vẻ như nó sẽ có một lợi ích hiệu suất: tại sao đánh giá những thứ mà thậm chí không bao giờ cần thiết?

Hơn nữa, giả sử bạn muốn thực hiện một chức năng if chấp nhận một boolean, và một đối tượng trả về nếu boolean là sự thật, và đối tượng khác quay trở lại nếu boolean là sai:

object if(bool condition, object valueIfTrue, object valueIfFalse) { 
    if(condition) return valueIfTrue; 
    return valueIfFalse; 
} 

Trong một ngôn ngữ mà háo hức đánh giá các đối số, cả hai đối tượng luôn được đánh giá mặc dù hàm sẽ luôn luôn chỉ cần một trong số chúng, trong đó, tốt nhất, phải gánh chịu một chi phí không cần thiết, và, tệ nhất, gây ra một vòng lặp vô hạn.

Điều đó nói rằng, vì hầu hết các ngôn ngữ lập trình sử dụng đánh giá mong muốn các đối số hàm, tôi cho rằng phải có lý do tại sao nó thường được thực hiện theo cách đó. Có một số lợi ích lớn của việc đánh giá háo hức ở đây mà tôi đang xem xét, chỉ vì nó dễ dàng hơn để thực hiện các ngôn ngữ theo cách đó, nó chỉ là truyền thống, hay cái gì?

+0

Bởi vì thật dễ dàng để biên dịch/giải thích mã bằng những ngôn ngữ không phải là ngôn ngữ lười biếng đó. –

Trả lời

5

Có một vài lý do tôi đã nhìn thấy để đánh giá háo hức, cả hai đều là quan trọng:

  1. đánh giá Háo hức có nghĩa là tác dụng phụ xảy ra ngay lập tức và luôn.Nếu bạn sử dụng đánh giá lười biếng, bạn không thể dựa vào các tác dụng phụ của một cái gì đó bạn đã thực hiện trước đó để có hiệu lực.
  2. Đánh giá lười biếng mang đến cho nó một số lượng nhất định của bộ nhớ sưng lên. Nó thường mất ít bộ nhớ hơn để lưu trữ kết quả tính toán hơn là lưu trữ số thunk mô tả phép tính. Điều này có thể dẫn đến việc sử dụng quá nhiều bộ nhớ (ví dụ, thời gian so với sự cân bằng bộ nhớ) và, đôi khi quan trọng hơn, một thời gian khó khăn hơn để tìm ra các đặc tính bộ nhớ của chương trình/thuật toán.

Đánh giá lười biếng có thể là công cụ mạnh mẽ, nhưng không phải không có chi phí. Ngôn ngữ thuần túy chức năng có xu hướng tránh vấn đề # 1 vì chúng không có tác dụng phụ (nói chung), nhưng vẫn bị cắn bởi vấn đề # 2 ở lần. Ngôn ngữ cho phép đánh giá trễ (các macro LISP là một dạng của điều này, mặc dù không giống như đánh giá lười biếng) có thể có tốt nhất của cả hai thế giới, nhưng với chi phí nỗ lực nhiều hơn trên phần của lập trình viên.

3

Lựa chọn 1 - tải tất cả đối số vào sổ đăng ký, gọi hàm

Lựa chọn 2 - tải đối số đầu tiên, đánh giá, nếu đó là cần thiết, chờ cho đường ống CPU để xóa, có được số tiếp theo, đánh giá, nếu đó là cần thiết .... sau đó tải các tham số cần thiết vào thanh ghi, thực thi hàm với logic phụ để đánh dấu thanh ghi nào đang được sử dụng.

Một 'nếu' đã được sẽ gây ra một cướp hiệu suất nào trong khi chờ đợi để xem mà mã con đường bạn đang thực hiện (hơi cứu bởi dự đoán rẽ nhánh)

3

Để đánh giá lười biếng làm việc cần có thêm mã và dữ liệu ở đâu đó để theo dõi xem biểu thức đã được đánh giá hay chưa. Trong một số trường hợp, điều này sẽ tốn kém hơn so với đánh giá háo hức. Xác định một biểu thức có thể hưởng lợi từ việc đánh giá lười biếng có thể đòi hỏi một kiến ​​thức rất cao về cách chương trình hoạt động; trình biên dịch và/hoặc thông dịch viên chắc chắn sẽ không có loại kiến ​​thức này.

Ngoài ra, nếu hàm hoặc biểu thức có tác dụng phụ, chiến lược đánh giá lười biếng có thể làm cho các chương trình hoạt động theo những cách phản trực giác và khó gỡ lỗi. Đây là khóa học không phải là một vấn đề trong ngôn ngữ lập trình chức năng mà không có tác dụng phụ của thiết kế. Trong thực tế, đánh giá lười biếng là chiến lược mặc định cho hầu hết, nếu không phải tất cả, ngôn ngữ lập trình chức năng.

Điều đó đang được nói, không có gì ngăn bạn sử dụng cả hai chiến lược ở những nơi khác nhau. Tôi sẽ không ngạc nhiên nếu một phương pháp lai được sử dụng trong các chương trình không tầm thường.

2

Ngoài những câu trả lời tuyệt vời đã được cung cấp, có một vấn đề thực tế khác với đánh giá lười biếng. Nếu bạn có một chuỗi các biểu thức chỉ được đánh giá một cách lười biếng khi lần cuối cùng được "sử dụng", nó có thể trở nên khá khó khăn để xác định các tắc nghẽn hiệu suất.

+0

Bạn có thể đưa ra một ví dụ không? Tôi đang cố gắng hình dung loại mã bạn đang nói đến. –

+0

Vâng, giả sử bạn có một đối số 'x' cho một hàm mà chính nó khi được đánh giá nhận giá trị của một biến' y' khác và loại chuỗi này quay trở lại. Có thể có một số đánh giá chậm và đó là tắc nghẽn nhưng bạn sẽ thấy chúng khi bạn đánh giá 'x'. Điều đó có thể gây hiểu lầm và nguồn gốc đôi khi khó theo dõi. –

0

Quay lại thời kỳ kỷ Phấn trắng, có một số ngôn ngữ đã thực hiện việc này. SNOBOL, chẳng hạn. ALGOL 68 có khả năng "gọi bằng tên", đã làm một việc như thế này. Và C (cũng như nhiều dẫn xuất của nó) làm điều đó trong một tình huống rất cụ thể, mà nó mô tả như là "ngắn mạch" một biểu thức boolean. Nói chung, nó gần như luôn luôn là một nguồn của nhiều sự nhầm lẫn và lỗi hơn là cho phép sức mạnh.

+0

Tôi không nghĩ rằng cuộc gọi của Algol theo tên là đánh giá lười biếng, tôi nghĩ rằng đó là truyền tham chiếu thay vì giá trị. –

+0

Cuộc gọi của ALGOL bằng tên là nhiều hơn một thay thế văn bản và rõ ràng không phải là một tham chiếu, vì vậy tôi nghĩ rằng nó đủ điều kiện để đánh giá lười biếng. Mặc dù bây giờ tôi nghĩ về nó, nó có thể đã được ALGOL 60 giới thiệu nó, không ALGOL 68. –

+1

Ahh ... những năm 1960, "[Cretaceous Period] (http://stackoverflow.com/questions/1463321/was -algol-bao giờ-được sử dụng-cho-chính-lập trình) "khi chúng tôi đã khổng lồ và đi trên mặt trăng ... :-) Algol60 đã gọi bằng tên. Algol68 không có cuộc gọi theo tên, tuy nhiên 68 không có cuộc gọi bằng cách tham khảo. Và hơn nữa, ... đánh giá lười biếng có thể được thực hiện trong một chương trình bởi coder bằng cách sử dụng "thủ tục", c.f. [Đánh giá ngắn mạch sử dụng quy trình] (http://stackoverflow.com/questions/9462051/short-circuit-evaluation-using-procedures) – NevilleDNZ

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