Lưu ý chắc chắn nếu điều này đủ điều kiện cho bạn, nhưng trong các ngôn ngữ chức năng như Standard ML, mọi thứ đều không thay đổi theo mặc định. Đột biến được hỗ trợ thông qua một loại ref
erence chung . Vì vậy, một int
biến là bất biến, và một ref int
biến là một thùng chứa có thể thay đổi cho int
s. Về cơ bản, các biến là các biến thực theo nghĩa toán học (một giá trị không xác định nhưng cố định) và ref
s là "biến" theo nghĩa lập trình mệnh lệnh - một ô nhớ có thể được ghi và đọc từ đó. (Tôi thích gọi chúng là chuyển nhượng .)
Tôi nghĩ rằng vấn đề với const
là hai lần. Đầu tiên, C ++ thiếu bộ sưu tập rác, cần thiết để có cấu trúc dữ liệu liên tục không tầm thường . const
phải sâu sắc để có ý nghĩa, nhưng có các giá trị bất biến hoàn toàn trong C ++ là không thực tế.
Thứ hai, trong C ++, bạn cần chọn tham gia const
thay vì từ chối. Nhưng khi bạn quên const
một cái gì đó và sau đó sửa nó, bạn sẽ gặp phải tình huống "ngộ độc const" được đề cập trong câu trả lời của @ RobY, nơi const
thay đổi sẽ xếp tầng trong toàn bộ mã. Nếu const
là mặc định, bạn sẽ không thấy mình áp dụng const
hồi tố. Ngoài ra, việc phải thêm const
ở mọi nơi sẽ tạo ra nhiều tiếng ồn cho mã.
Tôi nghi ngờ các ngôn ngữ chính tiếp theo (ví dụ Java) được định hình rất nhiều bởi sự thành công và cách suy nghĩ của C và C ++. Trường hợp cụ thể, ngay cả với bộ sưu tập rác, hầu hết các API bộ sưu tập của các ngôn ngữ đều giả định cấu trúc dữ liệu có thể thay đổi. Thực tế là tất cả mọi thứ đều có thể thay đổi và bất biến được xem như một trường hợp góc nói lên rất nhiều về tư duy bắt buộc đằng sau các ngôn ngữ phổ biến.
EDIT : Sau khi phản ánh nhận xét của greenoldman, tôi nhận ra rằng điều đó const
không trực tiếp về tính bất biến của dữ liệu; const
mã hóa thành kiểu của phương thức cho dù nó có tác dụng phụ trên thể hiện.
Có thể sử dụng đột biến để đạt được hành vi minh bạch tham chiếu . Giả sử bạn có một hàm mà khi được gọi liên tiếp trả về các giá trị khác nhau - ví dụ: một hàm đọc một ký tự từ đó stdin
. Chúng ta có thể sử dụng bộ đệm / ghi nhớ kết quả của hàm này để tạo ra một luồng giá trị trong suốt tham chiếu. Luồng sẽ là một danh sách được liên kết có các nút sẽ gọi hàm trong lần đầu tiên bạn cố truy xuất giá trị của chúng, nhưng sau đó lưu lại kết quả. Vì vậy, nếu là stdin
hằng số Hello, world!
, lần đầu tiên bạn cố gắng lấy giá trị của nút đầu tiên, nó sẽ đọc một nút char
và trả về H
. Sau đó, nó sẽ tiếp tục quay trở lại H
mà không cần gọi thêm để đọc a char
. Tương tự, nút thứ hai sẽ đọc char
từstdin
lần đầu tiên bạn cố gắng lấy lại giá trị của nó, lần này quay lại e
và lưu vào kết quả đó.
Điều thú vị ở đây là bạn đã biến một quá trình vốn đã thành trạng thái thành một đối tượng dường như không quốc tịch. Tuy nhiên, cần phải thay đổi trạng thái bên trong của đối tượng (bằng cách lưu trữ kết quả) để đạt được điều này - đột biến là một hiệu ứng lành tính . Không thể làm cho chúng tôi CharStream
const
mặc dù luồng hoạt động như một giá trị bất biến. Bây giờ hãy tưởng tượng có một Stream
giao diện với const
các phương thức và tất cả các chức năng của bạn đều mong đợi const Streams
. Bạn CharStream
không thể thực hiện giao diện!
( EDIT 2: Rõ ràng có một C ++ từ khóa gọi mutable
mà sẽ cho phép chúng tôi để lừa và làmCharStream
const
Tuy nhiên, lỗ hổng này phá hủy. const
S đảm bảo' - bây giờ bạn thực sự không thể chắc chắn điều gì đó sẽ không đột biến thông qua của nó const
phương pháp Tôi cho rằng nó không phải là. xấu vì bạn phải yêu cầu lỗ hổng một cách rõ ràng, nhưng bạn vẫn hoàn toàn phụ thuộc vào hệ thống danh dự.)
Thứ hai, giả sử bạn có các hàm bậc cao - nghĩa là bạn có thể truyền các hàm dưới dạng đối số cho các hàm khác. const
Ness là một phần của chữ ký của hàm, vì vậy bạn sẽ không thể chuyển các const
hàm không phải là đối số cho các hàm mong đợi các const
hàm. Thực thi một cách mù quáng const
ở đây sẽ dẫn đến mất tính tổng quát.
Cuối cùng, thao túng một const
đối tượng không đảm bảo rằng nó không làm biến đổi một số trạng thái bên ngoài (tĩnh hoặc toàn cầu) phía sau lưng của bạn, vì vậy const
, đảm bảo không mạnh như lúc ban đầu xuất hiện.
Tôi không rõ ràng rằng mã hóa sự hiện diện hay vắng mặt của các tác dụng phụ vào hệ thống loại là một điều tốt.