Tôi muốn hiểu ở mức độ thấp những gì sẽ xảy ra nếu cấu trúc dữ liệu không liên tục?
Chúng ta hãy xem một trình tạo số giả ngẫu nhiên với một không gian trạng thái khổng lồ (như " Mersenne twister " với trạng thái 2450 byte) dưới dạng cấu trúc dữ liệu. Chúng tôi không thực sự muốn sử dụng bất kỳ số ngẫu nhiên nào nhiều hơn một lần, vì vậy dường như có rất ít lý do để thực hiện điều này như một cấu trúc dữ liệu liên tục không thay đổi. Bây giờ hãy hỏi bên ngoài những gì có thể sai trong mã sau đây:
mt_gen = CreateMersenneTwisterPRNGen(seed)
integral = MonteCarloIntegral_Bulk(mt_gen) + MonteCarloIntegral_Boundary(mt_gen)
Hầu hết các ngôn ngữ lập trình không chỉ định thứ tự MonteCarloIntegral_Bulk
và MonteCarloIntegral_Boundary
sẽ được đánh giá. Nếu cả hai đều tham chiếu đến mt_gen có thể thay đổi làm đối số, kết quả của tính toán này có thể phụ thuộc vào nền tảng. Tệ hơn nữa, có thể có các nền tảng mà kết quả không thể lặp lại ở tất cả các lần chạy khác nhau.
Người ta có thể thiết kế một cấu trúc dữ liệu có thể thay đổi hiệu quả cho mt_gen sao cho bất kỳ sự xen kẽ nào của việc thực hiện MonteCarloIntegral_Bulk
và MonteCarloIntegral_Boundary
sẽ cho kết quả "chính xác", nhưng nói chung, một sự xen kẽ khác nhau sẽ dẫn đến một kết quả "chính xác" khác. Không tái sản xuất này làm cho chức năng tương ứng "không trong sạch", và cũng dẫn đến một số vấn đề khác.
Không thể lặp lại có thể tránh bằng cách thực thi một lệnh thực hiện tuần tự cố định. Nhưng trong trường hợp đó, mã có thể được sắp xếp theo cách mà chỉ một tham chiếu duy nhất đến mt_gen có sẵn tại bất kỳ thời điểm nào. Trong ngôn ngữ lập trình chức năng được gõ, các loại duy nhất có thể được sử dụng để thực thi ràng buộc này, do đó cho phép cập nhật có thể thay đổi an toàn trong bối cảnh ngôn ngữ lập trình chức năng thuần túy. Tất cả điều này nghe có vẻ hay và bảnh bao, nhưng ít nhất trong lý thuyết mô phỏng Monte Carlo là song song đáng xấu hổvà "giải pháp" của chúng tôi vừa phá hủy tài sản này. Đây không chỉ là một vấn đề lý thuyết, mà là một vấn đề thực tế rất thực tế. Tuy nhiên, chúng tôi phải sửa đổi (chức năng được cung cấp bởi) trình tạo số giả ngẫu nhiên của chúng tôi và chuỗi số ngẫu nhiên mà nó tạo ra và không có ngôn ngữ lập trình nào có thể tự động làm điều này cho chúng tôi. (Tất nhiên chúng ta có thể sử dụng một thư viện số giả ngẫu nhiên khác đã cung cấp các chức năng cần thiết.)
Ở mức độ thấp, các cấu trúc dữ liệu có thể thay đổi dễ dẫn đến không thể lặp lại (và do đó không có tạp chất), nếu thứ tự thực hiện không tuần tự và cố định. Một chiến lược bắt buộc điển hình để giải quyết các vấn đề này là có các giai đoạn liên tiếp với thứ tự thực hiện cố định, trong đó các cấu trúc dữ liệu có thể thay đổi được thay đổi và các giai đoạn song song với thứ tự thực hiện tùy ý, trong đó tất cả các cấu trúc dữ liệu có thể thay đổi được chia sẻ không đổi.
Andrej Bauer đưa ra vấn đề răng cưa cho các cấu trúc dữ liệu có thể thay đổi. Thật thú vị, các ngôn ngữ mệnh lệnh khác nhau như Fortran và C có các giả định khác nhau về việc đặt bí danh cho phép của các đối số hàm và hầu hết các lập trình viên đều không biết rằng ngôn ngữ của họ có mô hình răng cưa nào cả.
Tính bất biến và giá trị ngữ nghĩa có thể được đánh giá hơi cao. Điều quan trọng hơn là hệ thống loại và khung logic (như mô hình máy trừu tượng, mô hình bí danh, mô hình đồng thời hoặc mô hình quản lý bộ nhớ) của ngôn ngữ lập trình của bạn cung cấp đủ hỗ trợ để làm việc "an toàn" với dữ liệu "hiệu quả" cấu trúc. Việc giới thiệu "di chuyển ngữ nghĩa" cho C ++ 11 có thể trông giống như một bước lùi khổng lồ về độ tinh khiết và "an toàn" từ quan điểm lý thuyết, nhưng trên thực tế thì ngược lại. Hệ thống loại và khung logic của ngôn ngữ đã được mở rộng để loại bỏ những phần nguy hiểm lớn liên quan đến ngữ nghĩa mới. (Và ngay cả khi các cạnh gồ ghề vẫn còn, điều này không có nghĩa là điều này không thể được cải thiện bởi "tốt hơn"
Uday Reddy đưa ra vấn đề rằng toán học không bao giờ hoạt động với các đối tượng dữ liệu có thể thay đổi và các hệ thống loại cho các chương trình chức năng được phát triển tốt cho các đối tượng dữ liệu bất biến. Điều này khiến tôi nhớ đến lời giải thích của Jean-Yves Girard rằng toán học không được sử dụng để làm việc với các vật thể thay đổi, khi anh ta cố gắng thúc đẩy logic tuyến tính.
Người ta có thể hỏi làm thế nào để mở rộng hệ thống loại và khung logic của các ngôn ngữ lập trình chức năng để cho phép làm việc "an toàn" với các cấu trúc dữ liệu không liên tục "hiệu quả" có thể thay đổi. Một vấn đề ở đây có thể là logic cổ điển và đại số boolean có thể không phải là khung logic tốt nhất để làm việc với các cấu trúc dữ liệu có thể thay đổi. Có lẽ logic tuyến tính và đơn sắc giao hoán có thể phù hợp hơn cho nhiệm vụ đó? Có lẽ tôi nên đọc những gì Philip Wadler nói về logic tuyến tính như hệ thống kiểu cho các ngôn ngữ lập trình chức năng? Nhưng ngay cả khi logic tuyến tính không thể giải quyết vấn đề này, điều đó không có nghĩa là hệ thống loại và khung logic của ngôn ngữ lập trình chức năng không thể được mở rộng để cho phép "an toàn" và "hiệu quả"