+1

Một số kĩ thuật nâng cao khi sử dụng case trong Ruby

Đối với nhiều người, cú pháp case của Ruby chỉ đơn giản được kế thừa từ ngôn ngữ C, dùng để thay thế cho các cấu trúc if phức tạp. Sự thật là không chỉ có vậy, cấu trúc case được cài đặt và có thể thực hiện nhiều chức năng phức tạp hơn nhiều, ví dụ như:

case "Hi there"
when String
  puts "case statements match class"
end

# outputs: "case statements match class"

Ví dụ này cho ta thấy rằng cấu trúc case không chỉ có khả năng so sánh giá trị mà còn có thể so sánh các lớp. Điều này hoàn toàn hợp lý vì theo như cài đặt, Ruby sử dụng toán tử ===. Về toán tử ===: Khi ta viết x === y trong Ruby, có nghĩa là ta hỏi "toán tử y có thuộc nhóm được đại diện bởi x không?". Đây là câu hỏi rất rộng, và câu trả lời cho câu hỏi này phụ thuộc phần lớn vào các nhóm mà ta đang làm việc.

String === "hello" # true
String === 1 # false

Với toán tử ===, ta có thể thực hiện một số mẹo nhỏ với case:

So sánh bằng tập

Ta có thể dùng một tập các số nhờ vào việc khi sử dụng range == n, trình dịch sẽ tự hiểu là range.include?(n).

case 5
when (1..10)
  puts "case statements match inclusion in a range"
end

# outputs "case statements match inclusion in a range"

So sánh bằng biểu thức đại diện

Sử dụng regex trong cấu trúc case cũng hoàn toàn có thể, bởi vì /regexp/ === "string" sẽ trả về true khi string phù hợp với công thức regexp.

case "FOOBAR"
when /BAR$/
  puts "they can match regular expressions!"
end

# outputs "they can match regular expressions!"

So sánh bằng hàm

Đây là một trường hợp đặc biệt. Khi sử dụng Proc#===(item), điều đó đồng nghĩa với việc gọi Proc#call(item). Điều này có nghĩa là ta có thể dùng lamda và các hàm để so sánh động.

case 40
when -> (n) { n.to_s == "40" }
  puts "lambdas!"
end

# outputs "lambdas"

Tự viết class so sánh

Như được nhắc đến ở trên, việc thêm vào các trường hợp tự chọn trong case đồng nghĩa với việc ghi đè toán tử ===. Một trong những tác dụng chính của của phương pháp này là chia các biểu thức logic phức tạp ra thành các lớp. Tham khảo ví dụ dưới đây để hiểu rõ hơn phương pháp này:

class Success
  def self.===(item)
    item.status >= 200 && item.status < 300
  end
end

class Empty
  def self.===(item)
    item.response_size == 0
  end
end

case http_response
when Empty
  puts "response was empty"
when Success
  puts "response was a success"
end

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí