Một số kĩ thuật nâng cao khi sử dụng case trong Ruby
Bài đăng này đã không được cập nhật trong 9 năm
Đố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