Loại tẩy là tốt
Hãy bám sát sự thật
Cho đến nay, rất nhiều câu trả lời được người dùng Twitter quan tâm quá mức. Sẽ rất hữu ích nếu bạn tập trung vào tin nhắn chứ không phải người đưa tin. Có một thông điệp khá nhất quán với ngay cả những đoạn trích được đề cập cho đến nay:
Thật buồn cười khi người dùng Java phàn nàn về tính năng xóa kiểu, đó là điều duy nhất Java làm đúng, trong khi bỏ qua tất cả những điều nó sai.
Tôi nhận được những lợi ích khổng lồ (ví dụ như tham số) và chi phí không (chi phí bị cáo buộc là một giới hạn của trí tưởng tượng).
mới T là một chương trình bị hỏng. Nó đồng nghĩa với tuyên bố "tất cả các mệnh đề đều đúng." Tôi không quan tâm đến điều này.
Mục tiêu: các chương trình hợp lý
Những dòng tweet này phản ánh một quan điểm không quan tâm đến việc liệu chúng ta có thể khiến máy móc làm điều gì đó hay không , mà quan tâm hơn đến việc liệu chúng ta có thể lý giải rằng máy móc sẽ làm điều gì đó chúng ta thực sự muốn hay không. Lập luận tốt là một bằng chứng. Bằng chứng có thể được chỉ định trong ký hiệu chính thức hoặc một cái gì đó ít trang trọng hơn. Bất kể ngôn ngữ đặc tả là gì, chúng phải rõ ràng và chặt chẽ. Các đặc tả không chính thức không phải là không thể cấu trúc chính xác, nhưng thường có sai sót trong lập trình thực tế. Chúng tôi kết thúc với các biện pháp khắc phục như kiểm tra tự động và khám phá để bù đắp cho các vấn đề chúng tôi gặp phải với lý luận không chính thức. Điều này không có nghĩa là thử nghiệm về bản chất là một ý tưởng tồi, nhưng người dùng Twitter được trích dẫn đang gợi ý rằng có một cách tốt hơn nhiều.
Vì vậy, mục tiêu của chúng tôi là có các chương trình chính xác mà chúng tôi có thể lập luận một cách rõ ràng và chặt chẽ theo cách tương ứng với cách máy thực thi chương trình. Tuy nhiên, đây không phải là mục tiêu duy nhất. Chúng tôi cũng muốn logic của chúng tôi có một mức độ thể hiện. Ví dụ, chỉ có rất nhiều thứ mà chúng ta có thể diễn đạt bằng logic mệnh đề. Thật tuyệt khi có định lượng phổ quát (∀) và hiện sinh (∃) từ một cái gì đó giống như logic bậc nhất.
Sử dụng hệ thống kiểu để lập luận
Các mục tiêu này có thể được giải quyết rất tốt bởi các hệ thống loại. Điều này đặc biệt rõ ràng vì có thư từ Curry-Howard . Sự tương ứng này thường được thể hiện với sự tương tự sau đây: các loại là chương trình như định lý là chứng minh.
Thư từ này có phần sâu sắc. Chúng ta có thể lấy các biểu thức logic và dịch chúng thông qua sự tương ứng với các loại. Sau đó, nếu chúng ta có một chương trình có cùng kiểu chữ ký để biên dịch, chúng ta đã chứng minh rằng biểu thức logic là đúng phổ biến (một phép cộng). Điều này là do sự tương ứng là hai chiều. Việc chuyển đổi giữa kiểu / chương trình và thế giới định lý / chứng minh là cơ học và trong nhiều trường hợp có thể được tự động hóa.
Curry-Howard chơi một cách tuyệt vời những gì chúng tôi muốn làm với các thông số kỹ thuật cho một chương trình.
Các hệ thống kiểu có hữu ích trong Java không?
Ngay cả khi hiểu rõ về Curry-Howard, một số người vẫn thấy dễ dàng loại bỏ giá trị của một hệ thống kiểu, khi nó
- rất khó để làm việc với
- tương ứng (thông qua Curry-Howard) với một lôgic có khả năng diễn đạt hạn chế
- bị hỏng (được mô tả đặc tính của hệ thống là "yếu" hoặc "mạnh").
Về điểm đầu tiên, có lẽ IDE làm cho hệ thống kiểu của Java đủ dễ dàng để làm việc (điều đó rất chủ quan).
Về điểm thứ hai, Java gần như tương ứng với logic bậc một. Generics cho phép sử dụng hệ thống loại tương đương với định lượng phổ quát. Thật không may, các ký tự đại diện chỉ cung cấp cho chúng ta một phần nhỏ định lượng hiện sinh. Nhưng định lượng phổ quát là một khởi đầu khá tốt. Thật tuyệt khi có thể nói rằng các chức năng List<A>
hoạt động phổ biến cho tất cả các danh sách có thể có vì A hoàn toàn không bị giới hạn. Điều này dẫn đến những gì người dùng Twitter đang nói về "tham số".
Một bài báo thường được trích dẫn về tham số là Định lý của Philip Wadler miễn phí! . Điều thú vị về bài báo này là chỉ từ một chữ ký kiểu, chúng ta có thể chứng minh một số bất biến rất thú vị. Nếu chúng tôi viết các bài kiểm tra tự động cho những bất biến này, chúng tôi sẽ rất lãng phí thời gian của mình. Ví dụ, đối với List<A>
, chỉ từ chữ ký loại choflatten
<A> List<A> flatten(List<List<A>> nestedLists);
chúng ta có thể lập luận rằng
flatten(nestedList.map(l -> l.map(any_function)))
≡ flatten(nestList).map(any_function)
Đó là một ví dụ đơn giản và bạn có thể lý luận về nó một cách không chính thức, nhưng thậm chí còn đẹp hơn khi chúng tôi nhận được các bằng chứng như vậy chính thức miễn phí từ hệ thống loại và được kiểm tra bởi trình biên dịch.
Không xóa có thể dẫn đến lạm dụng
Từ góc độ triển khai ngôn ngữ, các chỉ số chung của Java (tương ứng với các kiểu phổ quát) đóng vai trò rất quan trọng trong tham số được sử dụng để có được bằng chứng về những gì chương trình của chúng tôi làm. Đây là vấn đề thứ ba được đề cập. Tất cả những lợi ích về chứng minh và tính đúng đắn này đòi hỏi một hệ thống loại âm thanh được thực hiện không có khiếm khuyết. Java chắc chắn có một số tính năng ngôn ngữ cho phép chúng ta phá vỡ lý luận của mình. Chúng bao gồm nhưng không giới hạn ở:
- tác dụng phụ với một hệ thống bên ngoài
- sự phản chiếu
Các yếu tố chung không bị xóa theo nhiều cách liên quan đến sự phản ánh. Không có sự tẩy xóa, có thông tin thời gian chạy được mang theo việc triển khai mà chúng ta có thể sử dụng để thiết kế các thuật toán của mình. Điều này có nghĩa là về mặt tĩnh, khi chúng ta lý luận về các chương trình, chúng ta không có bức tranh đầy đủ. Sự phản ánh đe dọa nghiêm trọng tính đúng đắn của bất kỳ bằng chứng nào mà chúng ta lý luận về mặt tĩnh. Không phải ngẫu nhiên mà sự phản chiếu cũng dẫn đến một loạt các khiếm khuyết phức tạp.
Vì vậy, những cách mà các generic không bị xóa có thể "hữu ích" là gì? Hãy xem xét cách sử dụng được đề cập trong tweet:
<T> T broken { return new T(); }
Điều gì xảy ra nếu T không có hàm tạo no-arg? Trong một số ngôn ngữ, những gì bạn nhận được là rỗng. Hoặc có lẽ bạn bỏ qua giá trị null và chuyển thẳng đến việc nâng cao một ngoại lệ (mà giá trị null dường như vẫn dẫn đến). Bởi vì ngôn ngữ của chúng ta là Turing hoàn chỉnh, nên không thể lý giải về việc lệnh gọi nào broken
sẽ liên quan đến các kiểu "an toàn" với các hàm tạo không đối số và những lệnh nào sẽ không. Chúng tôi đã đánh mất sự chắc chắn rằng chương trình của chúng tôi hoạt động trên toàn cầu.
Xóa có nghĩa là chúng tôi đã lý luận (vì vậy hãy xóa)
Vì vậy, nếu chúng tôi muốn lập luận về các chương trình của mình, chúng tôi đặc biệt khuyên không nên sử dụng các đặc điểm ngôn ngữ đe dọa mạnh mẽ đến lý luận của chúng tôi. Một khi chúng tôi làm điều đó, thì tại sao không chỉ bỏ các loại trong thời gian chạy? Chúng không cần thiết. Chúng ta có thể nhận được một số hiệu quả và sự đơn giản với sự hài lòng rằng không có phôi nào bị lỗi hoặc các phương thức có thể bị thiếu khi gọi.
Xóa khuyến khích lý luận.