Tôi không có bằng tiến sĩ, cũng không có loại bằng cấp nào khác về CS cũng không phải toán cũng như bất kỳ lĩnh vực nào khác. Tôi không có kinh nghiệm trước với Scala cũng như bất kỳ ngôn ngữ tương tự nào khác. Tôi không có kinh nghiệm với các hệ thống loại so sánh từ xa. Trong thực tế, ngôn ngữ duy nhất mà tôi có nhiều hơn là một kiến thức hời hợt trong đó thậm chí có một hệ thống loại là Pascal, không được biết đến chính xác với hệ thống loại tinh vi của nó. (Mặc dù nó không có các loại phạm vi, mà AFAIK khá nhiều ngôn ngữ không khác có, nhưng đó không phải là thực sự liên quan ở đây.) Ba ngôn ngữ khác mà tôi biết là BASIC, Smalltalk và Ruby, không ai trong số đó thậm chí còn có một hệ thống kiểu.
Tuy nhiên, tôi không gặp khó khăn gì trong việc hiểu chữ ký của map
chức năng bạn đã đăng. Dường như với tôi khá giống chữ ký map
có trong mọi ngôn ngữ khác mà tôi từng thấy. Sự khác biệt là phiên bản này là chung chung hơn. Nó trông giống như một thứ C ++ STL hơn là, nói, Haskell. Cụ thể, nó trừu tượng ra khỏi loại bộ sưu tập cụ thể bằng cách chỉ yêu cầu đối số đó IterableLike
và cũng trừu tượng khỏi loại trả về cụ thể bằng cách chỉ yêu cầu tồn tại một hàm chuyển đổi ẩn có thể tạo ra thứ gì đó từ tập hợp các giá trị kết quả đó. Vâng, điều đó khá phức tạp, nhưng nó thực sự chỉ là một biểu hiện của mô hình chung về lập trình chung: đừng cho rằng bất cứ điều gì bạn không thực sự phải làm.
Trong trường hợp này, map
thực sự không cần bộ sưu tập là một danh sách, hoặc được sắp xếp hoặc có thể sắp xếp hoặc bất cứ thứ gì tương tự. Điều duy nhất map
quan tâm là nó có thể có quyền truy cập vào tất cả các yếu tố của bộ sưu tập, từng cái một, nhưng không theo thứ tự cụ thể. Và nó không cần biết bộ sưu tập kết quả là gì, nó chỉ cần biết cách xây dựng nó. Vì vậy, đó là những gì chữ ký loại của nó yêu cầu.
Vì vậy, thay vì
map :: (a → b) → [a] → [b]
Chữ ký kiểu truyền thống map
là gì, nó được khái quát hóa để không yêu cầu cụ thể List
mà chỉ là một IterableLike
cấu trúc dữ liệu
map :: (IterableLike i, IterableLike j) ⇒ (a → b) → i → j
mà sau đó được khái quát hóa thêm bằng cách chỉ yêu cầu một hàm tồn tại có thể chuyển đổi kết quả thành bất kỳ cấu trúc dữ liệu nào mà người dùng muốn:
map :: IterableLike i ⇒ (a → b) → i → ([b] → c) → c
Tôi thừa nhận rằng cú pháp là một chút vụng về, nhưng ngữ nghĩa là như nhau. Về cơ bản, nó bắt đầu từ
def map[B](f: (A) ⇒ B): List[B]
đó là chữ ký truyền thống cho map
. (Lưu ý làm thế nào do tính chất hướng đối tượng của Scala, tham số danh sách đầu vào biến mất, bởi vì giờ đây nó là tham số máy thu ngầm mà mọi phương thức trong một hệ thống OO gửi đơn có.) Sau đó, nó khái quát từ cụ thể List
sang tổng quát hơnIterableLike
def map[B](f: (A) ⇒ B): IterableLike[B]
Bây giờ, nó thay thế IterableLike
bộ sưu tập kết quả bằng một hàm tạo ra , tốt, thực sự là về bất cứ thứ gì.
def map[B, That](f: A ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That
Mà tôi thực sự tin rằng không phải là điều đó khó có thể hiểu được. Thực sự chỉ có một vài công cụ trí tuệ mà bạn cần:
- Bạn cần biết (đại khái)
map
là gì . Nếu bạn chỉ đưa ra chữ ký loại mà không có tên của phương thức, tôi thừa nhận, sẽ khó hơn rất nhiều để tìm hiểu điều gì đang xảy ra. Nhưng vì bạn đã biết những gì map
cần phải làm và bạn biết chữ ký loại của nó là gì, bạn có thể nhanh chóng quét chữ ký và tập trung vào sự bất thường, như "tại sao điều này lại map
lấy hai chức năng làm đối số chứ không phải một?"
- Bạn cần phải có khả năng thực sự đọc chữ ký loại. Nhưng ngay cả khi bạn chưa bao giờ thấy Scala trước đây, điều này khá dễ dàng, vì nó thực sự chỉ là một hỗn hợp các cú pháp loại mà bạn đã biết từ các ngôn ngữ khác: VB.NET sử dụng dấu ngoặc vuông cho đa hình tham số và sử dụng một mũi tên để biểu thị Kiểu trả về và dấu hai chấm để phân tách tên và loại, thực sự là chuẩn.
- Bạn cần biết đại khái về lập trình chung là gì. (Mà không phải là điều đó khó có thể tìm ra, vì nó về cơ bản tất cả các giải thích rõ ràng trong tên: nó theo nghĩa đen chỉ lập trình một cách chung chung).
Không ai trong số ba người này nên làm cho bất kỳ lập trình viên chuyên nghiệp hoặc thậm chí sở thích đau đầu nghiêm trọng. map
là một chức năng tiêu chuẩn trong hầu hết mọi ngôn ngữ được thiết kế trong 50 năm qua, thực tế là các ngôn ngữ khác nhau có cú pháp khác nhau nên rõ ràng đối với bất kỳ ai đã thiết kế trang web với HTML và CSS và bạn không thể đăng ký chương trình thậm chí từ xa danh sách gửi thư liên quan mà không có một số fanboy C ++ khó chịu từ nhà thờ St. Stepanov giải thích những ưu điểm của lập trình chung.
Vâng, Scala rất phức tạp. Vâng, Scala có một trong những hệ thống loại tinh vi nhất mà con người biết đến, cạnh tranh và thậm chí vượt qua các ngôn ngữ như Haskell, Miranda, Clean hoặc Cyclone. Nhưng nếu sự phức tạp là một lập luận chống lại sự thành công của ngôn ngữ lập trình, C ++ sẽ chết từ lâu và tất cả chúng ta sẽ viết Scheme. Có rất nhiều lý do khiến Scala rất có thể sẽ không thành công, nhưng thực tế là các lập trình viên không thể bận tâm để bật bộ não của họ trước khi ngồi xuống trước bàn phím có lẽ sẽ không phải là chính.