Swift - Custom operators - Part 2
Swift - Custom operators - Part 2 Ở Part 1: https://kipalog.com/posts/Swift---Custom-operators---Part-1, mình đã giới thiệu cơ bản về operator và cách custom nó. Trong phần 2 này mình sẽ đi sau tìm hiểu thêm 1 số phần khác nâng cao hơn chút. 1. Generic Operators Bây giờ mình muốn phép luỹ ...
Swift - Custom operators - Part 2
Ở Part 1: https://kipalog.com/posts/Swift---Custom-operators---Part-1, mình đã giới thiệu cơ bản về operator và cách custom nó. Trong phần 2 này mình sẽ đi sau tìm hiểu thêm 1 số phần khác nâng cao hơn chút.
1. Generic Operators
Bây giờ mình muốn phép luỹ thừa apply cho toàn bộ các loại Integer. Code như sau, cũng khá dễ hiểu:
func **<T: Integer>(lhs: T, rhs: Int) -> T { var result = lhs for _ in 2...rhs { result *= lhs } return result } func **=<T: Integer>(lhs: inout T, rhs: Int) { lhs = lhs ** rhs }
Chú ý đến Integer type constrain. Cái ràng buộc cần có bởi vì dòng code: có operator *= không phải loại nào cũng dùng được, phải conform Integer Type mới dùng được. Bây giờ ta test thử với các loại Integer khác nhau:
let unsignedBase: UInt = 2 let unsignedResult = unsignedBase ** exponent let base8: Int8 = 2 let result8 = base8 ** exponent let unsignedBase8: UInt8 = 2 let unsignedResult8 = unsignedBase8 ** exponent let base16: Int16 = 2 let result16 = base16 ** exponent let unsignedBase16: UInt16 = 2 let unsignedResult16 = unsignedBase16 ** exponent let base32: Int32 = 2 let result32 = base32 ** exponent let unsignedBase32: UInt32 = 2 let unsignedResult32 = unsignedBase32 ** exponent let base64: Int64 = 2 let result64 = base64 ** exponent
Như vậy, nó đúng cho tất cả các loại integer: Int, UInt, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64 and UInt64. Int/ UInt/ Int8 là gì các bạn tự tìm hiểu thêm nha.
2. Precedence and associativity
Nếu chỉ có 2 giá trị thì khá đơn giản nhưng nếu là đoạn code sau thì sao:
2 * 2 ** 3 ** 3 // không thể compile
Swift không thể compile được nếu thiếu các thông tin sau đây:
- Độ ưu tiên (precedence): Phép nào trước phép nào, nhân trước hay luỹ thừa trước.
- Độ kết hợp (associativity): Từ trái qua phải trước hay từ phải qua trái trước.
Nếu không có 2 thông tin trên thì có 1 cách duy nhất để Swift hiểu và compile, đó là quăng vào dấu ngoặc đơn:
2 * (2 ** (3 ** 2))
Để tránh khỏi sự phiền hà, ta chỉ cần define ra precedence group như sau:
precedencegroup ExponentiationPrecedence { associativity: right higherThan: MultiplicationPrecedence } infix operator **: ExponentiationPrecedence
Cái mà mình define ở trên là ưu tiên phép luỹ thừa trên phép nhân (MultiplicationPrecedence), và phép tính sẽ là từ phải sang trái (associativity: right). Bây giờ thì Swift có thể compile mà không cần thêm gì nữa.
Như vậy, qua 2 phần, mình đã giới thiệu thêm cho các bạn cụ thể về Custom Operators. Hi vọng các bạn có thêm được phần kiến thức bổ ích cho mình.