operator

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ỹ 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.

Registration Login
Sign in with social account
or
Lost your Password?
Registration Login
Sign in with social account
or
A password will be send on your post
Registration Login
Registration