Thành thạo Ruby Block trong 5 phút
Bài đăng này đã không được cập nhật trong 6 năm
Block
trong ngôn ngữ ruby là gì?
Về cơ bản, block
trong ruby là đoạn code
nằm giữa do
và end
.
Chúng ta có hai cách viết block
:
- Viết thành nhiều dòng, viết giữa
do
vàend
- Viết 1 dòng, viết giữa hai dấu
{
và}
Cả hai cách đều cho ra một kết quả giống nhau, nhưng khi dòng code của bạn quá dài thì nên lựa chọn cách viết thứ 2, bởi nó giúp code của dễ đọc hơn .
Ví dụ :
Khi viết code nhiều dòng
[1, 2, 3].each do |n|
puts "Number #{n}"
end
Có thể viết thành một dòng như:
[1, 2, 3].each {|n| puts "Number #{n}"}
|n|
được gọi là tham số block (block parameter)
, giá trị của nó trong trường hợp này được gọi lần lượt theo giá trị của mảng đã cho, đầu tiên nhận giá trị là 1, lần thứ 2 là 2, cuối cùng là 3
Kết quả:
Number 1
Number 2
Number 3
=> [1, 2, 3]
yield
làm việc như nào ?
yield
là một phần sức mạnh của ruby block
, nó chịu trách nhiệm về mọi sự ảo diệu cũng như nhầm lẫn trong block
. Phần lớn sự nhầm lẫn đều đến từ cách gọi block
và việc làm thế nào để truyền tham số vào trong nó
Chúng ta hãy xem ví dụ sau:
def my_method
puts "reached the top"
yield
puts "reached the bottom"
end
my_method do
puts "reached yield"
end
Kết quả:
reached the top
reached yield
reached the bottom
=> nil
Về cơ bản, khi bạn thực thi my_method
và đến dòng gọi đến yield
, nó sẽ chuyển đến gọi block truyền tham số. Sau đoạn code bên trong block chạy xong, nó sẽ lại tiếp tục chạy code trong hàm my_method
tiếp
Một điều lưu ý ở đây là các tham số bên trong block
là cục bộ đối với block
(không giống như các tham số được truyền từ phương thức vào block
).
Đưa vào yield
nhiều tham số
Bất kỳ tham số nào được truyền cho yield
sẽ đóng vai trò là tham số của một block
. Vì vậy, khi block
chạy, nó có thể sử dụng các tham số được truyền từ phương thức ban đầu. Các tham số này có thể trở thành biến địa phương (variables local) đối với phương thức trong yield
Thứ tự của các đối số truyền vào cũng rất quan trọng bởi vì thứ tự bạn sắp xếp cũng là thứ tự mà phương thức đó nhận được nó
Ý nghĩa của &block
Bạn có thể nhìn thấy &block
được xuất hiện rất nhiều nơi trong các đoạn code của ruby. Đây là cách bạn có thẻ tham chiếu đến block
(thay vì sử dụng biến địa phương) cho một phương thức. Trên thực tế, ruby cho phép bạn truyền bất kỳ đối tượng nào thành phương thức như thể nó là một block
. Phương thức sẽ cố gắng đưa đội tượng về dạng block
, nhưng nếu nó không phải dạng block
sẽ gọi to_proc
vào trong để chuyển đổi nó về dạng block
def my_method(&block)
puts block
block.call
end
my_method { puts "Hello!" }
Kết quả:
#<Proc:0x0000010124e5a8@tmp/example.rb:6>
Hello!
Biến block
bên trong phương thức my_method
là một tham chiếu đến block
và nó có thể thực hiện bằng phương thức call
. call
trong block
giống như sử dụng yield
. Một vài người thích sử dụng call
vì nó dễ hiểu code hơn yield
.
Trả về giá trị
yield
trả về giá trị cuối cùng (bên trong block
). Nói cách khác, giá trị mà yield
trả về là giá trị của block
def my_method
value = yield
puts "value is: #{value}"
end
my_method do
2
end
Kết quả:
value is 2
=> nil
Sử dụng vòng lặp trong block
Bạn có thể gọi đến yield
nhiều lần, đó là lúc bạn nên sử dụng đến vòng lặp.
def my_map(array)
new_array = []
for element in array
new_array.push yield element
end
new_array
end
my_map([1, 2, 3]) do |number|
number * 2
end
Kết quả:
2
4
6
Khởi tạo đối tượng với các giá trị mặc định
Cách mà nó làm việc là viết trong hàm khởi tạo của ruby (initialize
) có sử dụng yield(self)
, trong đó self
là đối tượng được khởi tạo
class Car
attr_accessor :color, :doors
def initialize
yield(self)
end
end
car = Car.new do |c|
c.color = "Red"
c.doors = 4
end
puts "My car's color is #{car.color} and it's got #{car.doors} doors."
Kết quả:
My car's color is Red and it's got 4 doors.
Tổng kết
Block
là một trong những tính năng mạnh mẽ của ruby nhưng thường xuyên bị bỏ quên. Bạn có thể thấy block
không chỉ đơn giản là một đoạn code giữa do
và end
, mà trong bài này ta còn được biết đến yield
, nó cho phép bạn chèn các đoạn code vào bất cứ đâu trong phương thức. Điều đó có nghĩa là bạn có một phương thức mà có nhiều cách hoạt động khác nhau giống như có nhiều phương thức.
Hi vọng bài viết trên giúp bạn trong việc hiểu và sử dụng block
và trợ thủ yield
Tài liệu tham khảo: https://mixandgo.com/blog/mastering-ruby-blocks-in-less-than-5-minutes Mastering ruby blocks in less than 5 minutes của tác giả Cezar Halmagean
All rights reserved