yield_self trong ruby 2.5
Chúng ta đang rất chờ đón sự phát hành của ruby 2.5 với rất nhiều những tính năng thú vị. Trong đó, có một tính năng sẽ khiến bạn phải siêu lòng, đó là method yield_self. yield_self được định nghĩa như sau: # object.yield_self {|x| block } → an_object # Yields self to the block and returns ...
Chúng ta đang rất chờ đón sự phát hành của ruby 2.5 với rất nhiều những tính năng thú vị. Trong đó, có một tính năng sẽ khiến bạn phải siêu lòng, đó là method yield_self. yield_self được định nghĩa như sau:
# object.yield_self {|x| block } → an_object # Yields self to the block and returns the result of the block. class Object def yield_self yield(self) end end
yield_self là một method của class Object, nó sẽ trả về một block với dữ liệu nhận vào chính là đối tượng gọi method, kết quả trả về của block đó là một đối tượng mới. Đơn giản hơn thì chúng ta có thể nhìn vào một ví dụ như sau:
"123456".yield_self {|string| string.to_i } # => 123456
Kết quả từ đối tượng String, trả về đối tượng Number. Nghe có vẻ cầu kỳ, vậy tại sao ko dùng "123456".to_i đi cho rồi??? Nếu đơn giản vậy thì không phải dĩ nhiên là nhà phát hành cho hàm này có mặt trong phiên bản sắp tới. Tất nhiên là nó đều có mặt tốt và không tốt, tùy vào trường hợp chúng ta sử dụng. Ta có một ví dụ tiếp theo: Khi không sử dụng yield_self
CSV.parse(File.read(File.expand_path("data.csv"), __dir__)) .map { |row| row[1].to_i } .sum
Nhìn qua thì cũng phải mất vài giây để bạn có thể hiểu được. Lý do là bình thường chúng ta đọc từ trái qua phải, nhưng dòng code lại chạy từ phải qua trái. Còn khi sử dụng yield_self thì sao:
"data.csv" .yield_self { |name| File.expand_path(name, __dir__) } .yield_self { |path| File.read(path) } .yield_self { |body| CSV.parse(body) } .map { |row| row[1].to_i } .sum
Bạn thấy tốt hơn hay tồi tệ hơn?? Mình không nghĩ đó là một giải pháp hữu hiệu nhưng chúng ta có thể thấy được một số lợi ích của nó:
- Có một flow rõ ràng từ trên xuống dưới
- Code dễ dàng chỉnh sửa nếu thêm nhiều logic khác.
Nhược điểm:
- Code hơi rườm rà với nhiều block không cần thiết
- Không phải chỉ như vậy mà nó là 1 tính năng mới.
Chúng ta thử ví dụ tiếp theo.
"https://api.github.com/repos/rails/rails" .yield_self { |url| URI.parse(url) } .yield_self { |url| Net::HTTP.get(url) } .yield_self { |response| JSON.parse(response) } .yield_self { |repo| repo.fetch("stargazers_count") } .yield_self { |stargazers| "Rails has #{stargazers} stargazers" } .yield_self { |string| puts string }
chúng ta dễ hiểu hơn rất nhiều, thay vì viết thành nhiều câu lệnh khác nhau hoặc lồng nhau.
Object#yield_self là một công cụ khá hưu ích để xây dựng một hệ thống dữ liệu nối tiếp nhau, từ block này đến block khác. Chúng ta hãy cân nhắc để sử dụng nó một cách thật phù hợp.
Trên đây là tất cả những gì về method yield_self, các bạn biết thêm 1 tính năng cũng khá thú vị phải không?