12/08/2018, 16:46

Khác nhau giữa block, proc và lambda trong ruby

Định nghĩa đơn giản là cách chúng ta nhóm những đoạn code vào 1 chỗ và gọi ra để chạy khi cần # Block Examples [1,2,3].each { |x| puts x*2 } # block được giới hạn bởi dấu {} [1,2,3].each do |x| puts x*2 # block được giới hạn bởi do và end end # Proc Examples ...

Định nghĩa đơn giản là cách chúng ta nhóm những đoạn code vào 1 chỗ và gọi ra để chạy khi cần

# Block Examples

[1,2,3].each { |x| puts x*2 }   # block được giới hạn bởi dấu {}

[1,2,3].each do |x|
  puts x*2                    # block được giới hạn bởi do và end
end

# Proc Examples             
p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p)              # Ký tự '&' bảo ruby  đưa các proc (các giá trị của array) vào trong block mà proc đấy định nghĩa

proc = Proc.new { puts "Hello World" }
proc.call                     # block mà proc đấy định nghĩa đc thực thi khi gọi hàm call từ proc

# Lambda Examples            
lam = lambda { |x| puts x*2 }
[1,2,3].each(&lam)

lam = lambda { puts "Hello World" }
lam.call

Nhìn qua thấy chúng rất giống nhau, đều là định nghĩa các block rồi đưa biêns vào thực thi block đấy sau đây là sự khác nhau

  1. Proc là 1 object, block không phải, block chỉ đơn giản là 1 khối lệnh
p = Proc.new { puts "Hello World" }

tạo 1 instance của proc

p.call  # prints 'Hello World'
p.class # returns 'Proc'
a = p   # a now equals p, a Proc instance
p       # returns a proc object '#<Proc:0x007f96b1a60eb0@(irb):46>'

Trong khi đó, block chỉ là 1 khối lệnh và ko có ý nghĩa gì hết, cũng ko gán qua gán lại được

{ puts "Hello World"}       # syntax error  
a = { puts "Hello World"}   # syntax error
[1,2,3].each {|x| puts x*2} # only works as part of the syntax of a method call

Cả proc và lambdas đều là proc object

proc = Proc.new { puts "Hello world" }
lam = lambda { puts "Hello World" }

proc.class # returns 'Proc'
lam.class  # returns 'Proc'

Tuy nhiên lambdas khác đôi chút

proc   # returns '#<Proc:0x007f96b1032d30@(irb):75>'
lam    # returns '<Proc:0x007f96b1b41938@(irb):76 (lambda)>'
  1. Lambdas check số lượng tham số truyên vào còn proc thì không
lam = lambda { |x| puts x }    # creates a lambda that takes 1 argument
lam.call(2)                    # prints out 2
lam.call                       # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3)                # ArgumentError: wrong number of arguments (3 for 1)
proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument
proc.call(2)                   # prints out 2
proc.call                      # returns nil
proc.call(1,2,3)               # prints out 1 and forgets about the extra arguments
  1. Lambas và proc luận giải 'return' khác nhau
def lambda_test
  lam = lambda { return }
  lam.call
  puts "Hello world"
end

lambda_test                 # calling lambda_test prints 'Hello World'

return của lambda đựoc kích hoạt code ngay bên ngoài lambda code

def proc_test
  proc = Proc.new { return }
  proc.call
  puts "Hello world"
end

proc_test                 # calling proc_test prints nothing

return của proc kích hoạt code bên ngoài cái method mà proc đấy đc thực thi

0