2017-06-12 18 views

Trả lời

2

Gọi By Name:

Gọi theo tên là một chiến lược đánh giá nơi đối số cho hàm không được đánh giá trước khi hàm được gọi-đúng hơn, họ được thay thế trực tiếp vào cơ quan chức năng (sử dụng Capture- tránh thay thế) và sau đó để được đánh giá bất cứ khi nào chúng xuất hiện trong hàm. Nếu một đối số không được sử dụng trong thân hàm, thì đối số sẽ không bao giờ được đánh giá; nếu nó được sử dụng nhiều lần, nó sẽ được đánh giá lại mỗi khi nó xuất hiện. (Xem Thiết bị của Jensen.)

Đánh giá từng cuộc gọi đôi khi thích hợp hơn để đánh giá theo từng giá trị. Nếu đối số của hàm không được sử dụng trong hàm, gọi theo tên sẽ tiết kiệm thời gian bằng cách không đánh giá đối số, trong khi gọi theo giá trị sẽ đánh giá nó bất kể. Nếu đối số là một tính toán không chấm dứt, lợi thế là rất lớn. Tuy nhiên, khi đối số chức năng được sử dụng, gọi theo tên thường chậm hơn, đòi hỏi một cơ chế như một đoạn.

Sử dụng sớm là ALGOL 60. Các ngôn ngữ .NET ngày nay có thể mô phỏng cuộc gọi theo tên bằng cách sử dụng các đại biểu hoặc tham số biểu thức. Kết quả cuối cùng trong một cây cú pháp trừu tượng được gán cho hàm. Eiffel cung cấp các đại lý, đại diện cho một hoạt động được đánh giá khi cần thiết. Seed7 cung cấp các cuộc gọi theo tên với các tham số hàm.

Gọi By Macro:

Gọi bởi sự mở rộng vĩ mô cũng tương tự như gọi bằng tên, nhưng sử dụng thay thế văn bản chứ không phải là thay thế chụp-tránh. Với việc sử dụng không thận trọng, việc thay thế macro có thể dẫn đến việc thu thập biến và dẫn đến hành vi không mong muốn. Các macro hợp vệ sinh tránh được vấn đề này bằng cách kiểm tra và thay thế các biến được tô bóng không phải là các tham số.

LƯU Ý: Trong ngôn ngữ đánh giá không đúng

Ví dụ Gọi By Macro:

Gọi bởi Expansion Macro: nhiều ngôn ngữ lập trình, bao gồm C, lisp chương trình và cung cấp các nhà phát triển với một cơ chế để thêm cú pháp mới vào ngữ pháp ngôn ngữ cốt lõi được gọi là macro. Macro được mở rộng thành mã bằng bộ tiền xử lý macro. Các macro này có thể chứa đối số, trong đó được sao chép trong mã cuối cùng mà trình tiền xử lý tạo ra. Như một ví dụ , chương trình C dưới đây thực hiện các chức năng trao đổi thông qua một vĩ mô:

#define SWAP(X,Y) {int temp=X; X=Y; Y=temp;} int main() { int a = 2; int b = 3; printf("%d, %d\n", a, b); SWAP(a, b); printf("%d, 
> %d\n", a, b); } 

Macro này thực hiện một thói quen trao đổi hợp lệ.

chương trình được xử lý trước sẽ giống như mã bên dưới.Vì nội dung của macro được sao chép trực tiếp vào văn bản của chương trình gọi điện, nó hoạt động theo ngữ cảnh của chương trình đó. Nói cách khác, macro sẽ chuyển trực tiếp đến tên biến mà nó nhận và không được để giá trị của chúng.

int main() { int a = 2; int b = 3; printf("%d, %d\n", a, b); { 
> int tmp = (a); (a) = (b); (b) = tmp; }; printf("%d, %d\n", a, b); } 

Các biểu thức truyền cho vĩ mô như các thông số được đánh giá mỗi thời gian chúng được sử dụng trong cơ thể của vĩ mô. Nếu đối số là không bao giờ được sử dụng, sau đó nó chỉ đơn giản là không được đánh giá. Ví dụ: chương trình bên dưới sẽ tăng biến b hai lần:

#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) int main() { int a = 2, b = 3; int c = MAX(a, b++); printf("a = %d, b = %d, c = %d\n", a, b, c); } Macro gặp phải một sự cố, được gọi là chụp biến. Nếu macro xác định biến v đã được xác định trong môi trường của người gọi và v được chuyển đến macro dưới dạng tham số, thì nội dung của macro sẽ không thể phân biệt một lần xuất hiện của v từ khác. Ví dụ, chương trình dưới đây có một macro xác định temp biến. Cuộc gọi bên trong chính gây ra nhiệt độ biến được xác định bên trong chức năng này để được chụp theo định nghĩa bên trong phần thân macro .

#define SWAP(X,Y) {int temp=X; X=Y; Y=temp;} int main() { int a = 2; int temp = 17; printf("%d, temp = %d\n", a, temp); SWAP(a, temp); 
> printf("%d, temp = %d\n", a, temp); } 

Sau khi chương trình này được mở rộng bởi

C Preprocessor, chúng tôi nhận được mã dưới đây. Chương trình này không trao đổi các giá trị của các biến tạm thời và một:

int main() { int a = 2; int temp = 17; printf("%d, temp = %d\n", 
> a, temp); {int temp=a; a=temp; temp=temp;}; printf("%d, temp = 
> %d\n", a, temp); } 

Có một số các chiến lược đánh giá lười biếng

mà tránh được những vấn đề chụp biến. Hai kỹ thuật nổi tiếng nhất là là gọi theo tên và gọi theo nhu cầu.

Ví dụ Gọi tên theo:

Gọi theo Tên: trong chiến lược đánh giá này tham số thực tế là chỉ đánh giá nếu được sử dụng bên trong hàm; tuy nhiên, đánh giá này sử dụng ngữ cảnh của thói quen người gọi. Ví dụ, trong ví dụ dưới đây, lấy từ sách của Weber, chúng ta có hàm g trả về số nguyên 6. Bên trong hàm f, phép gán đầu tiên, ví dụ, b = 5, lưu trữ 5 trong biến i. Bài tập thứ hai, b = a, đọc giá trị của i, hiện tại là 5 và thêm 1 cho nó. Giá trị này sau đó được lưu trữ tại i.

void f(by-name int a, by-name int b) { 
    b=5; 
    b=a; 
} 
int g() { 
    int i = 3; 
    f(i+1,i); 
    return i; 
} 

Rất ít ngôn ngữ thực hiện cuộc gọi theo chiến lược đánh giá tên. Các nổi tiếng nhất trong số những ngôn ngữ này là Algol. Simula, một hậu duệ trực tiếp của Algol, cũng thực hiện cuộc gọi theo tên, như chúng ta có thể thấy trong ví dụ này là . Cuộc gọi theo tên luôn luôn gây ra việc đánh giá tham số , ngay cả khi tham số này được sử dụng nhiều lần.Hành vi này có thể lãng phí trong các ngôn ngữ minh bạch tham chiếu, bởi vì, trong các biến ngôn ngữ này là không thay đổi.

+0

Cảm ơn @sugansoft, nhưng điều này có vẻ như một bản sao dán từ https://en.wikibooks.org/wiki/Introduction_to_Programming_Languages/Evaluation_Strategies. Sự khác biệt và lợi thế/bất lợi giữa cả hai chiến lược đánh giá không được nêu chi tiết trong câu trả lời của bạn. –

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