BẮT ĐẦU
KIỂU DỮ LIỆU
TOÁN TỬ
NÂNG CAO
INTERVIEW
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
Dự án mới của mình là gamehow.net, mời anh em ghé thăm và góp ý ạ.

Block trong Ruby

Trong bài viết lần này, mình sẽ chia sẻ vơi các bạn về một kiến thức sẽ rất hay được sử dụng trong ngôn ngữ lập trình Ruby, đó chính là block. Block chính là một trong những tính năng mạnh mẽ nhất của Ruby.

1. Block là gì ?

Block là một khối lệnh được đặt trong do...end, chúng ta có 2 cách viết đối với một block.

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Với những đoạn code nhiều dòng sẽ được đặt trong do...end

[1, 2, 3].each do |n|
  puts "Số #{n}"
end

Đối với những ngắn, có thể viết trên một dòng thì chúng ta đặt trong 2 dấu ngoặc nhọn {}

[1, 2, 3].each {|n| puts "Số #{n}"}

Kết quả

Số 1
Số 2
Số 3

Cả hai cách viết trên đều cho chúng ta kết quả giống nhau. Có một điều đặc biệt đó chính là |n|, đây là tham số được truyền vào block với giá trị lần lượt tương ứng với các giá trị trong mảng là 1, 2 và 3.

Đối với những đoạn code dài dòng từ 2 trở nên, các bạn nên sử dụng cách viết đặt trong do..end để code trong clear và dễ đọc hơn.

Tham số trong block được đặt trong dấu | thay vì dấu ngoặc đơn như cách chúng ta truyền tham số ở method

2. Sử dụng yield trong Block

Từ khóa yield có thể coi là một trong những "sức mạnh" của block. Nó giúp chúng ta thực hiện một khối lệnh trong block mà không ảnh hưởng gì tới các đoạn code xung quanh.

Khi làm việc với method chúng ta có thể truyền trực tiếp block vào method dưới dạng như là một tham số.

Ví dụ mình có một hàm viết như thế này

def hello
  puts "Hello"
end

hello

Kết quả

Hello

Giờ chúng ta sẽ thử truyền một block vào method

def hello
  puts "Hello"
end

hello { puts "Code truyền vào method" }

Kết quả vẫn sẽ là Hello.

Để chúng ta có thể thực thi được đoạn code bên trong block mà chúng ta truyền vào method hello thì sẽ sử dụng đến yield. Để hiểu dễ hơn chúng ta sẽ xem qua ví dụ luôn

def hello
  puts "Hello"
  yield
  puts "Goodbye"
end

hello { puts "Code truyền vào method" }

Kết quả

Hello
Code truyền vào method
Goodbye

Khi chúng ta sử dụng method hello nó sẽ thực thi lần lượt các đoạn code được viết trong hàm và khi đến dòng yield, nó sẽ gọi đến block mà chúng ta đã truyền vào. Sau khi đoạn code bên trong block thực thi xong, các đoạn code tiếp bên trong method sẽ được thực thi tiếp.

Nếu chúng ta khia báo yield mà không truyền block vào method thì sẽ gây ra lỗi và đoạn code bên dưới yield sẽ không được thực thi

Ví dụ

def hello
  puts "Hello"
  yield
  puts "Goodbye"
end

hello

Kết quả

Hello
Traceback (most recent call last):
	1: from loop.rb:7:in `<main>'
loop.rb:3:in `hello': no block given (yield) (LocalJumpError)

Đoạn code bên trên yield vẫn sẽ được thực thi cho đến khi yield được gọi tới.

3. Kiểm tra sự tồn tại của block

Như mình đã nói ở phần trên, khi chúng ta sử dụng yield mà lại quên mất việc truyền block vào method thì sẽ gây ra lỗi chương trình.

Để kiểm soát được việc này theo mình nên cẩn thận kiểm tra xem có tồn tại block hay không, nếu không thì bỏ qua để tránh gây ra lỗi không mong muốn.

Muốn kiểm tra được sự tồn tại của block chúng ta sẽ sử dụng phương thức block_given?

def hello
  puts "Hello"
  return yield if block_given?
  puts "Goodbye"
end

hello

Kết quả

Hello
Goodbye

4. Truyền tham số vào yield

Ở phần trên chúng ta đã biết yield nhận vào một block và thực thi code trong block đó, ngoài ra chúng ta cũng có thể truyền thêm tham số vào trong yield. Bất kì tham số nào được truyền vào trong yield sẽ đóng vai trò là tham số của block.

Ví dụ

def hello
  puts "Hello"
  return yield('Phú', 22) if block_given?
  puts "Goodbye"
end

hello do |name, age|
  puts "Xin chào tôi là #{name}, năm nay tôi #{age} tuổi"
end

Kết quả

Hello
Xin chào tôi là Phú, năm nay tôi 22 tuổi

Các tham số được truyền vào yield sẽ chỉ có phạm vi cục bộ bên trong block mà bạn truyền vào, tức là nó chỉ có giá trị bên trong block đó mà thôi.

Thứ tự tham số bạn truyền vào trong yield sẽ tương ứng với các tham số mà chúng ta sẽ gọi ở bên trong block.

Có thể thấy, các tham số bên trong |...| sẽ chứa các tham số của block với giá trị tương ứng được truyền từ yield vào.

5. Giá trị trả về

yield sẽ trả về giá trị của biểu thức cuối cùng trong block, tức là kết quả trả về của block sẽ tương ứng với kết quả của yield.

def hello
  value = yield
  puts "Kết quả của yield là #{value}"
end

hello do
  1 + 1
end

Kết quả

2

6. &block là gì ?

&block là một đối với những newbie mới học Ruby thì chắc sẽ khá lạ lẫm. Khi tiếp xúc và làm việc với Ruby thì có thể bạn sẽ rất hay gặp &block xuất hiện trong code của bạn.

Ở phần trên mình đã giới thiệu với các bạn về việc sử dụng yield để gọi tới block. Còn một cách nữa giúp chúng ta tham chiếu tới block đó chính là sử dụng &block.

Lưu ý là chúng ta cần phải đặt tiền tố là & để tham chiếu tới block.

Ruby cho phép bạn truyền bất cứ đối tượng nào thành phương thức như thể nó là một block. Ruby sẽ xử lý đối tượng này để chuyển chúng về dạng block

Ví dụ

def hello &block
  puts block
  block.call
end

hello do
  puts "#{1+1}"
end

Đọc doạn code trên chúng ta sẽ thấy biến block trong method hello sẽ tham chiếu đến block. Lúc này, biến block sẽ là một Proc. Cụ thể hơn về Proc các bạn hãy xem ở bài tiếp theo, mình sẽ giải thích kỹ hơn.

Để có thể thực thi được các đoạn mã bên trong block chúng ta cần phải gọi đến một phương thức là call. Đây cũng giống như cái cách mà chúng ta làm việc với yield, chỉ khác là thay vì sử dụng yield chúng ta sẽ sử dụng một đối tượng Proc và gọi đến phương thức call để thực thi block.

Kết quả

#<Proc:0x00005563e3e56db0@loop.rb:6>
2

Tùy vào sở thích mỗi người mà sẽ lựa chọn sử dụng call hoặc yield. Tuy nhiên về phần hiệu năng thì yield sẽ mang lại một tốc độ tốt hơn so với cách chúng ta sử dụng call.

7. Kết luận

Ở bài này mình đã giới thiệu với các bạn về block trong Ruby, đây là một kiến thức quan trọng mà chúng ta cần phải hiểu và nắm rõ thì mới có thể làm việc với chúng dễ dàng và hiệu quả hơn. Thế nên, các bạn hãy học phần block này cẩn thận nhé.

Cùng chuyên mục:

Iterator trong Ruby

Iterator trong Ruby

Ở bài trước mình có nói với các bạn về việc sử dụng các vòng…

Vòng lặp trong Ruby: Vòng lặp for / while / until / loop

Vòng lặp trong Ruby: Vòng lặp for / while / until / loop

Khi học một ngôn ngữ lập trình thì không thể không tìm hiểu tới một…

Câu lệnh điều kiện trong Ruby

Câu lệnh điều kiện trong Ruby

Trong bài này chúng ta sẽ học các lệnh điều kiện trong Ruby, đây là…

Các toán tử trong Ruby

Các toán tử trong Ruby

Nói đến toán tử thì dù bạn học ngôn ngữ nào đi nữa thì việc…

Cách sử dụng Ranges trong Ruby

Cách sử dụng Ranges trong Ruby

Ví dụ bạn cần tạo ra một dãy từ 1 đến 100 thì có thể…

Cách sử dụng Array trong Ruby

Cách sử dụng Array trong Ruby

Đây cũng là một trong những kiểu dữ liệu phổ biến nhất, vì vậy bạn…

Kiểu dữ liệu Symbol trong Ruby

Kiểu dữ liệu Symbol trong Ruby

Symbol giống như một String thế nhưng Symbol là một chuỗi bất biến nghĩa là…

Kiểu dữ liệu Text trong Ruby (còn gọi là chuỗi / string)

Kiểu dữ liệu Text trong Ruby (còn gọi là chuỗi / string)

Kiểu dữ liệu Boolean trong Ruby: True, False và Nil

Kiểu dữ liệu Boolean trong Ruby: True, False và Nil

Boolean là kiểu dữ liệu rất quan trọng, nó được dùng rất nhiều trong những…

Kiểu dữ liệu Hashes trong Ruby: Hiểu từ đơn giản đến phức tạp

Kiểu dữ liệu Hashes trong Ruby: Hiểu từ đơn giản đến phức tạp

Nếu bạn đã từng làm việc với một vài ngôn ngữ khác trước khi mà…

Hiểu về Method Missing trong Ruby

Hiểu về Method Missing trong Ruby

Chắc hẳn với các lập trình viên chúng ta ai cũng có thể đôi lần…

Kiểu dữ liệu Number trong Ruby (Kiểu số Integer, Float, ...)

Kiểu dữ liệu Number trong Ruby (Kiểu số Integer, Float, ...)

Trước tiên, chúng ta cùng nhìn qua một bức ảnh tổng quát phân cấp các…

Ruby là gì? Ai đã sáng tạo ra ngôn ngữ viêm kim cương này?

Ruby là gì? Ai đã sáng tạo ra ngôn ngữ viêm kim cương này?

Từ những năm 2008, thời mà mình còn học đại học thì Ruby là ngôn…

Các loại biến và cách sử dụng Module trong Ruby

Các loại biến và cách sử dụng Module trong Ruby

Bất kì một ngôn ngữ lập trình nào đều có khái niệm biến và ruby…

Cách tạo Method - Class và Object trong Ruby

Cách tạo Method - Class và Object trong Ruby

Trong bài này mình sẽ hướng dẫn các bạn cách tạo hàm, gọi hàm. Cách…

Cú pháp trong Ruby - Chạy Hello World

Cú pháp trong Ruby - Chạy Hello World

Tổng quan về cú pháp trong ruby. Hướng dẫn tạo file và chạy hello world…

Hướng dẫn cài đặt Ruby trên Window, Linux và MacOS

Hướng dẫn cài đặt Ruby trên Window, Linux và MacOS

Hướng dẫn chi tiết cách thiết lập môi trường lập trình Ruby trên hệ điều…

Top