Cách rõ ràng nhất:
type Num = {
def +(a: Num): Num
def *(a: Num): Num
}
def pyth[A <: Num](a: A, b: A)(sqrt: A=>A) = sqrt(a * a + b * b)
// usage
pyth(3, 4)(Math.sqrt)
Đây là khủng khiếp vì nhiều lý do. Đầu tiên, chúng ta có vấn đề về kiểu đệ quy, Num
. Điều này chỉ được phép nếu bạn biên dịch mã này với tùy chọn -Xrecursive
được đặt thành một số giá trị số nguyên (5 có thể là quá đủ cho số). Thứ hai, loại Num
là cấu trúc, có nghĩa là bất kỳ việc sử dụng nào các thành viên mà nó định nghĩa sẽ được biên dịch thành các lời gọi phản chiếu tương ứng. Đặt nhẹ nhàng, phiên bản pyth
này không hiệu quả một cách tối đa, chạy theo thứ tự của một số trăm nghìn lần chậm hơn so với triển khai thông thường. Không có cách nào xung quanh loại cấu trúc mặc dù nếu bạn muốn xác định pyth
cho bất kỳ loại nào xác định +
, *
và có chức năng sqrt
.
Cuối cùng, chúng tôi gặp vấn đề cơ bản nhất: vấn đề quá phức tạp. Tại sao phải thực hiện chức năng theo cách này? Thực tế, các loại duy nhất mà nó cần phải áp dụng là số Scala thực. Do đó, đơn giản nhất là chỉ cần làm như sau:
def pyth(a: Double, b: Double) = Math.sqrt(a * a + b * b)
Tất cả các vấn đề được giải quyết! Hàm này có thể sử dụng được trên các giá trị của loại Double
, Int
, Float
, thậm chí là số lẻ như Short
nhờ vào sự tuyệt vời của chuyển đổi tiềm ẩn. Mặc dù đúng là chức năng này ít linh hoạt về mặt kỹ thuật so với phiên bản có cấu trúc của chúng tôi, nó là bao la hiệu quả hơn và dễ đọc hơn. Chúng tôi có thể đã mất khả năng tính toán định lý Pythagrean cho các loại không lường trước được xác định +
và *
, nhưng tôi không nghĩ rằng bạn sẽ bỏ lỡ khả năng đó.
Nguồn
2009-01-28 05:29:38
Và bây giờ tôi cuối cùng đã biết lý do tại sao các loại cấu trúc sẽ không cho phép tôi làm điều đó: http://article.gmane.org/gmane.comp.lang.scala/7013 –