5

Tại sao một số ngôn ngữ phân biệt giữa các phương thức trả lại giá trị và phương thức không trả về?Tại sao phân biệt giữa các phương thức trả về giá trị và phương thức không trả về?

tức là trong PL/SQL của Oracle, nơi khác biệt chính giữa hàm và thủ tục là hàm phải trả về giá trị và quy trình phải không.

Tương tự như vậy đối với các ngôn ngữ không, tại sao không?


EDIT: Tôi đã tìm thấy một câu hỏi liên quan có thể quan tâm người đọc câu hỏi này:

Trả lời

26

Vì tôi n các quan niệm ban đầu của lý thuyết và thực hành Khoa học Máy tính, các chức năng và các chương trình con hầu như không liên quan gì đến nhau.

FORTRAN thường được coi là ngôn ngữ đầu tiên triển khai cả hai điều này và thể hiện sự khác biệt. (LISP sớm có vai trò hơi đối lập trong điều này, nhưng nó có ít tác động bên ngoài học viện).

Theo truyền thống của toán học (mà CS vẫn là một phần trong thập niên 60) chỉ được xem là sự đóng gói các tính toán toán học được chỉ định để trả về giá trị thành biểu thức lớn hơn. Mà bạn có thể gọi nó là "trần" (F = AZIMUTH (SECONDS)) chỉ là một trường hợp sử dụng tầm thường.

Trình thủ tục, mặt khác được xem như một cách để đặt tên cho một nhóm các câu lệnh có nghĩa là có một số hiệu ứng. Các tham số là một sự thúc đẩy rất lớn cho khả năng sử dụng của chúng và lý do duy nhất là chúng được phép trả về các giá trị tham số đã sửa đổi để chúng có thể báo cáo trạng thái của chúng mà không phải dựa vào các biến toàn cầu.

Vì vậy, chúng thực sự không có kết nối khái niệm, ngoài việc đóng gói và tham số.

Câu hỏi thực sự là: "Có bao nhiêu nhà phát triển đến xem chúng giống nhau?"

Và câu trả lời cho đó là C.

Khi K + R được thiết kế ban đầu cao cấp vĩ mô ngôn ngữ kiểu lắp ráp của họ cho PDP-11 (có thể đã bắt đầu trên PDP-8?), Họ không có ảo tưởng về sự độc lập phần cứng. Hầu như mọi tính năng "duy nhất" của ngôn ngữ là sự phản ánh ngôn ngữ và kiến ​​trúc máy PDP (xem i ++ và --i). Một trong số đó là việc thực hiện các hàm và các chương trình con có thể (và luôn luôn) được thực hiện giống hệt trong PDP ngoại trừ người gọi vừa bỏ qua giá trị trả về (trong R0 [, R1]) cho các chương trình con.

Vì vậy, sinh ra con trỏ rỗng, và sau khi ngôn ngữ C đã chiếm toàn bộ thế giới lập trình, nhận thức sai lầm rằng hiện vật thực thi HW/OS này (mặc dù đúng trên hầu hết mọi nền tảng tiếp theo) giống như ngữ nghĩa ngôn ngữ .

+1

một câu trả lời tuyệt vời! –

+0

Tôi đồng ý. Đó có lẽ là câu trả lời sai từ quan điểm ngữ nghĩa hoặc lý thuyết, nhưng lý do thực sự có lẽ là lịch sử như được trích dẫn! – Yttrill

3

Trong một tinh khiết hoặc hiệu lực thi hành, đánh máy đang ngồi đó là một thế giới của sự khác biệt , bởi vì rõ ràng các phương pháp "không trả lại bất cứ điều gì" chỉ hữu ích cho các tác dụng phụ của chúng.

Điều này tương tự với sự khác biệt giữa biểu thức và câu lệnh, có thể làm suy giảm ngôn ngữ và loại bỏ một lớp chương trình thường bị nhầm lẫn (dĩ nhiên, đó là lý do tại sao C không làm điều đó;)).

Để đưa ra một ví dụ nhỏ, khi bạn phân biệt rõ ràng giữa các biểu thức và câu lệnh, if(x = 3), trái ngược với if(x == 3) là không chính xác (để sử dụng câu lệnh có biểu thức) và không chỉ lỗi kiểu nơi một boolean được mong đợi). Điều này có lợi ích của việc không cho phép if(x = true) được phép theo quy tắc dựa trên loại trong ngữ cảnh trong đó nhiệm vụ là các biểu thức có giá trị toán hạng bên phải của chúng.

Trong một ngôn ngữ mà gói gọn tác với monads, sự khác biệt quan trọng trở thành một giữa:

  • chức năng mà trở () đó là chức năng thuần túy và chỉ có thể trả lại một giá trị rỗng vô dụng gọi () hoặc bất đồng
  • các hàm trả về IO() (hoặc đơn vị trong một số đơn vị khác) là các hàm không có "kết quả" ngoại trừ các hiệu ứng trong đơn IO (hoặc bất kỳ) nào đơn lẻ
+0

Giải thích tuyệt vời, tuy nhiên, các biểu thức ví dụ dường như giả sử C. – RBarryYoung

+0

C phân biệt rõ ràng giữa các biểu thức và câu lệnh. Tuy nhiên, 'x = foo' là một biểu thức, đánh giá giá trị được gán. Điều này làm cho các thành ngữ nhất định ngắn gọn hơn nhiều (ví dụ: ngã ba, lặp lại không xác định). – Novelocrat

+1

Theo định nghĩa riêng của nó, nó có. Theo định nghĩa phổ biến hơn, nó không. 'x = foo' có một tác dụng phụ (về cơ bản nó * là * một tác dụng phụ, đó là" giá trị "được định nghĩa để thuận tiện chỉ để C có thể coi nó như là một biểu thức). Tôi không hiểu điểm của bạn về việc lặp lại vô thời hạn, bạn có thể đưa ra một ví dụ không? 'while (true) {whatever}' có vẻ ngắn gọn đối với tôi, và tôi không thể nhìn thấy một cách rõ ràng để làm tốt hơn bằng cách xử lý các bài tập như là các biểu thức? Ngoài ra, "sự phân biệt" của C bị phá vỡ bởi vì (AFAIK) bất kỳ biểu thức nào cũng có thể được sử dụng như một câu lệnh, không phải là trường hợp trong các ngôn ngữ chọn lọc. –

0

Xin lỗi trả lời một câu hỏi cũ hai năm, đặc biệt là với một cái gì đó độc đáo sang ngôn ngữ của riêng tôi Felix http://felix-lang.org nhưng ở đây đi dù sao đi nữa :)

Trong Felix, chức năng và thủ tục là nền tảng khác nhau, và nó không phải là chỉ là thủ tục có tác dụng phụ và được gọi trong báo cáo, trong khi chức năng không có tác dụng phụ và được sử dụng trong các biểu thức (vì Felix cũng có máy phát điện có chức năng với tác dụng phụ .. :)

Không, mô hình thực hiện là về cơ bản khác nhau, chủ yếu vì lý do hiệu suất, nhưng không hoàn toàn. Mô hình là:

  • Chức năng đặt địa chỉ trả lại của chúng trên ngăn xếp máy và giá trị trả về cũng vậy.
  • Thủ tục sử dụng danh sách được liên kết trên heap. Mã thủ tục là phẳng, nó không sử dụng ngăn xếp máy.

Điều này thường không hiệu quả, vậy tại sao phải làm như vậy? Câu trả lời là: thủ tục Felix là tất cả các khả năng đồng-thói quen (sợi). Họ có thể chuyển quyền kiểm soát sang thủ tục khác bằng cách truy cập kênh. Điều này gây ra sự trao đổi quyền kiểm soát.

  • Vì lý do hiệu suất, sao chép ngăn xếp máy trên trao đổi điều khiển không phải là một tùy chọn.
  • Vì lý do quản lý bộ nhớ, việc đổi chồng con trỏ cũng không phải là một tùy chọn.

Hệ điều hành thường hoán đổi con trỏ ngăn xếp cho chủ đề, nhanh chóng hợp lý nhưng có vấn đề cơ bản trên máy địa chỉ tuyến tính: bạn phải giới hạn kích thước tối đa của ngăn xếp thành giá trị nhỏ hoặc hạn chế kích thước số lượng chủ đề đến một giá trị nhỏ vô lý. Trên một máy 32 bit, không có đủ không gian địa chỉ để thậm chí chiêm ngưỡng giải pháp này. Trên máy tính 64 bit, hoán đổi ngăn xếp có nhiều tiềm năng hơn, nhưng tất nhiên nhu cầu của người dùng luôn phát triển để vượt qua phần cứng 3 ngày sau khi nó được phát hành .. :)

Felix chỉ hoán đổi một con trỏ duy nhất tới ngăn xếp dựa trên đống, vì vậy các thiết bị chuyển mạch bối cảnh nhanh chóng và không gian địa chỉ rất ít bị lãng phí. Tất nhiên chi phí là phân bổ đống trên các cuộc gọi thủ tục.Trong trình biên dịch, rất nhiều kiến ​​trúc của mô hình lý thuyết được tối ưu hóa trên cơ sở "as-if", vì vậy hiệu năng và thực hiện thực tế có thể khác với mô hình lý thuyết, miễn là trình biên dịch có thể chứng minh rằng bạn không thể nói sự khác biệt .. khác hơn là bị từ chối cơ hội để làm một tách cà phê với giải trí :)

Vì vậy, ở đây, bạn có một câu trả lời khác là tại sao các chức năng và quy trình có thể được xử lý khác nhau.

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