Các ngôn ngữ có sự phân biệt rõ ràng giữa các chương trình con hoàn toàn là chức năng, đột biến, thay đổi trạng thái, v.v?


8

Gần đây tôi càng trở nên thất vọng vì trong hầu hết các ngôn ngữ lập trình hiện đại tôi đã làm việc với (C / C ++, C #, F #, Ruby, Python, JS và hơn thế nữa), có rất ít, nếu có, hỗ trợ ngôn ngữ để xác định những gì một chương trình con thực sự sẽ làm.

Hãy xem xét mã giả đơn giản sau đây:

var x = DoSomethingWith(y);

Làm cách nào để xác định cuộc gọi đến DoS SomethingWith (y) sẽ thực sự làm gì? Nó sẽ biến đổi y , hoặc nó sẽ trả lại một bản sao của y ? Nó phụ thuộc vào nhà nước toàn cầu hay địa phương, hay nó chỉ phụ thuộc vào y ? Nó sẽ thay đổi nhà nước toàn cầu hoặc địa phương? Làm thế nào để đóng cửa ảnh hưởng đến kết quả của cuộc gọi?

Trong tất cả các ngôn ngữ tôi đã gặp, hầu như không có câu hỏi nào trong số những câu hỏi này có thể được trả lời bằng cách chỉ nhìn vào chữ ký của chương trình con, và hầu như không có bất kỳ hỗ trợ nào trong thời gian biên dịch hoặc thời gian chạy. Thông thường, cách duy nhất là đặt niềm tin của bạn vào tác giả của API và hy vọng rằng tài liệu và / hoặc quy ước đặt tên tiết lộ những gì chương trình con sẽ thực sự làm.

Câu hỏi của tôi là: Có tồn tại bất kỳ ngôn ngữ nào ngày nay tạo ra sự khác biệt mang tính biểu tượng giữa các loại kịch bản này và đặt các ràng buộc về thời gian biên dịch lên mã nào bạn thực sự có thể viết không?

(Tất nhiên có một số hỗ trợ cho điều này trong hầu hết các ngôn ngữ hiện đại, chẳng hạn như mức độ phạm vi và mức đóng khác nhau, sự tách biệt giữa mã tĩnh và mã thể hiện, hàm lambda, et cetera. Nhưng những điều này dường như thường mâu thuẫn với nhau. Ví dụ, một hàm lambda thường sẽ hoàn toàn là chức năng và chỉ cần trả về một giá trị dựa trên các tham số đầu vào hoặc thay đổi các tham số đầu vào theo một cách nào đó. Nhưng thường có thể truy cập các biến tĩnh từ hàm lambda, do đó có thể cung cấp cho bạn quyền truy cập vào các biến thể hiện và sau đó tất cả bị phá vỡ.)


1
Lưu ý rằng "hoàn toàn chức năng" là mơ hồ. Bạn có thể có nghĩa là "tinh khiết" (không có tác dụng phụ); "Hàm" ngụ ý một mô hình lập trình coi các hàm là các đối tượng hạng nhất và cho phép các hàm bậc cao hơn. Các chức năng đó không nhất thiết phải thuần túy và hầu hết các ngôn ngữ lập trình chức năng cho phép các chức năng không tinh khiết.
tdammers

Nghe có vẻ như một sự phân biệt ngữ nghĩa quan trọng để thực hiện. Ý tôi là với chức năng là theo nghĩa toán học, tức là thường trình chỉ phụ thuộc vào dữ liệu đầu vào, và không đọc và ghi vào bất kỳ dữ liệu nào khác trong chương trình. "Hàm thuần túy" có phải là một thuật ngữ chính xác hơn để mô tả điều này không?
Christian Palmstierna

Câu trả lời:


10

Vâng, bạn muốn nhìn vào Haskell. Nó làm chính xác những gì bạn muốn. Tất cả các chức năng là thuần túy theo mặc định và chỉ có thể thay đổi trạng thái bằng cách sử dụng Monads. Ngoài ra Haskell có các đảm bảo tĩnh rất mạnh về tất cả các loại http://learnyouahaskell.com/


Ah! Tôi đã nghe rất nhiều điều hay về Haskell, nhưng không thể tìm hiểu sâu về nó. Có lẽ nó sẽ phù hợp với hóa đơn của tôi :)
Christian Palmstierna

Dường như đó là nơi có rất nhiều điều thú vị đang diễn ra
Zachary K

5
Monads không thể biến đổi trạng thái nhiều hơn các loại dữ liệu khác; chúng bị ràng buộc bởi các ràng buộc độ tinh khiết giống như phần còn lại của ngôn ngữ. Rốt cuộc, không có gì đặc biệt về họ, ngoài một số cú pháp đường. Những gì họ có thể làm là cung cấp một sự trừu tượng hóa thuận tiện đối với mã tích lũy trạng thái thông qua các lệnh gọi hàm hoặc chuỗi đệ quy, và khi được biên dịch theo thời gian chạy, mã đó sẽ chuyển thành mã bắt buộc tương tự như mã đơn sắc. Mặc dù vậy, đây vẫn là một bản tóm tắt và mã vẫn hoàn toàn 100%.
tdammers

4
Ngoài ra, các hàm không thuần túy theo mặc định, chúng là thuần, theo thời gian. Haskell không thể thể hiện chức năng không tinh khiết.
tdammers

3
@CPX: Có ít nhất ba khung web mạnh về ngành cho Haskell (Yesod, Happstack và Snap) và rất nhiều thư viện cho thực tế tất cả các nhiệm vụ bạn đề cập (mặc dù không chắc chắn về SOAP); chất lượng mã trung bình trong hệ sinh thái Haskell có xu hướng tuyệt vời. Vấn đề lớn nhất tôi có thể thấy trước là tìm đủ lập trình viên để hỗ trợ một việc như vậy trong thời gian bảo trì dài hơn.
tdammers

6

CC ++ có hỗ trợ rất hạn chế cho ít nhất một phần của vấn đề thông qua consttừ khóa; trong khi điều này một mình không kiểm soát độ tinh khiết, nó có thể được sử dụng (đặc biệt là trong C ++) để báo cho trình biên dịch rằng cấu trúc dữ liệu cụ thể không được sửa đổi thông qua một con trỏ đã cho. Một số trình biên dịch (ví dụ gcc) cũng cung cấp thuộc tính 'thuần' như một phần mở rộng ngôn ngữ để thực thi đầy đủ độ tinh khiết. (Xem câu hỏi này để biết chi tiết).

Các D ngôn ngữ lập trình có hỗ trợ cho tuyên bố sự tinh khiết của các chức năng một cách rõ ràng, và trình biên dịch sẽ kiểm tra và thực thi tinh khiết (có nghĩa là, cố gắng để gọi một hàm phi tinh khiết từ bên trong một hàm thuần túy mang lại một lỗi biên dịch).

Haskell hoàn toàn thuần túy, nghĩa là bản thân ngôn ngữ không thể diễn tả các chức năng không trong sạch và không có khái niệm về 'thói quen'. Bất cứ điều gì không thể được giải quyết chỉ bằng các hàm thuần túy đều được gia công cho thời gian chạy (không tinh khiết); một chương trình với các tác dụng phụ được thực hiện bằng cách xây dựng (sử dụng các cấu trúc thuần túy) một cấu trúc dữ liệu lười biếng mô tả hành vi của chương trình, và sau đó đưa nó vào thời gian chạy. Cộng đồng Haskell đang tích cực thử nghiệm với cả một sở thú ngôn ngữ lập trình, một số trong số chúng thuần túy, một số khác có độ tinh khiết rõ ràng.

Có thể có nhiều hơn, nhưng đây là những cái tôi quen thuộc.


gcc không hỗ trợ các tuyên bố rõ ràng về độ tinh khiết như một phần mở rộng như vậy
Vô dụng

Các hàm thành viên const của C ++ thực hiện kiểm soát độ tinh khiết, nếu các lớp của bạn không có các hàm thành viên không phải là const. Tất cả dữ liệu trở nên không đổi, và sau đó mọi thứ là chức năng thuần túy.
tp1

@ tp1: Không hẳn. Hàm const thành viên có thể dễ dàng tạo ra các hiệu ứng phụ bằng cách gọi các phương thức tĩnh không const của các lớp khác, khởi tạo các lớp khác hoặc chỉ đơn giản gọi các hàm miễn phí hoặc sửa đổi các biến toàn cục. Nó chỉ hoạt động nếu bạn khóa toàn bộ cơ sở mã của mình thành all-const, bao gồm tất cả các thư viện bạn sử dụng (thậm chí STL).
tdammers

@tdammers: Khóa all-const không tệ lắm vì dữ liệu có thể được khởi tạo thành các giá trị khác nhau bằng các tham số của hàm tạo. Nhưng nó yêu cầu tất cả dữ liệu của bạn được đặt bên trong các lớp của bạn chứ không phải trong các biến toàn cục.
tp1

@ tp1: Điều đó cũng rất không thực tế, vì nó làm giảm số lượng thư viện bạn có thể sử dụng một cách an toàn xuống thực tế.
tdammers

1

Có vẻ như có ba loại:

  1. chức năng

    There is a rule for functions: 
    
    A function introduced by a fun binder is not allowed to have any side effects.
    
    The compiler does not enforce this rule, but it does take advantage of it when
    optimising your code. 
    
  2. thủ tục

    Procedures do not return a value, and may and generally should have side-effects.
    
  3. máy phát điện

    A generator is a function that may have side effects.
    

Điều này nghe có vẻ như một ngôn ngữ cố gắng làm chính xác những gì tôi đang theo đuổi. Thật không may là các chức năng không được thực thi bởi trình biên dịch, mặc dù (sau một vài năm làm việc chuyên nghiệp, tôi đã phát triển một sự ngờ vực đầu gối cho các thư viện lập trình viên khác ;-)). Ngoài ra, vì nó rất mới, tôi có thể sửa đổi nó, nhưng nó không giống như một ứng cử viên cho sự phát triển thương mại / chuyên nghiệp :(
Christian Palmstierna

1
@ChristianPalmstierna: Chỉ tình cờ gặp câu hỏi cũ này. Thật không may, giống như rất nhiều tính chất thú vị, quyết định xem một hàm có thuần túy hay không, tương đương với việc giải quyết vấn đề Dừng. Lưu ý rằng điều này không nhất thiết có nghĩa là bạn không thể làm điều đó, nó chỉ có nghĩa là có vô số hàm thuần túy mà trình biên dịch không thể chứng minh và do đó phải từ chối là không tinh khiết mặc dù chúng không. (Đây không phải là khác nhau từ typechecking tĩnh, mặc dù thường, có vô số các chương trình mà được an toàn nhưng không thể được chứng minh kiểu an không chỉ dừng lại chúng ta khỏi gõ...)
Jörg W Mittag
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.