2009-09-06 28 views

Trả lời

96

block chỉ là biến cục bộ, &block là tham chiếu đến khối được chuyển đến phương thức.

def foo(block = nil) 
    p block 
end 

foo # => nil 
foo("test") # => test 
foo { puts "this block will not be called" } # => nil 

def foo(&block) 
    p block 
end 

foo # => nil 
foo("test") # => ArgumentError: wrong number of arguments (1 for 0) 
foo { puts "This block won't get called, but you'll se it referenced as a proc." } 
# => #<Proc:[email protected]:20> 

Bạn cũng có thể sử dụng &block khi gọi phương pháp để vượt qua một proc như một khối đến một phương pháp, do đó bạn có thể sử dụng procs cũng giống như bạn sử dụng các khối.

my_proc = proc {|i| i.upcase } 

p ["foo", "bar", "baz"].map(&my_proc) 
# => ["FOO", "BAR", "BAZ"] 

p ["foo", "bar", "baz"].map(my_proc) 
# => ArgumentError: wrong number of arguments (1 for 0) 

Tên biến block không có ý nghĩa gì đặc biệt. Bạn có thể sử dụng &strawberries nếu muốn, ký hiệu là khóa ở đây.

Bạn có thể tìm thấy this article hữu ích.

+28

+1 cho '' '& strawberries''' – raycchan

+1

Tôi sẽ thêm: nó tương tự như cách bạn sử dụng toán tử splat (tức là '*') cho mảng:' def foo (* args) ; other_foo (* args); end' sẽ lấy một mảng đối số tùy ý, và sau đó truyền mảng đó vào hàm gọi bên trong. Với các khối, bạn sẽ làm 'def foo (& block); other_foo (& block); kết thúc' –

27

Trong danh sách đối số, &whatever lấy khối được chuyển đến phương thức và kết thúc nó trong đối tượng Proc. Các Proc được lưu trữ trong một biến gọi là whatever (nơi mà có thể được bất cứ tên nào bạn gõ sau khi ký hiệu và, tất nhiên - thường là "khối"). Sau khi gọi phương thức, cú pháp &whatever biến Proc thành một khối. Vì vậy, nếu bạn xác định một phương pháp như vậy:

def thing(&block) 
    thing2 &block 
end 

Bạn đang xác định một phương thức có khối và sau đó gọi một phương thức khác với khối đó.

16

Nếu bạn không đặt & trước khi chặn, Ruby sẽ không nhận ra mối quan hệ của nó với "khối" bạn chuyển đến hàm. Dưới đây là một số ví dụ.

def f(x, block); end 
f(3) { 2+2 } # gives an error, because "block" is a 
       # regular second argument (which is missing) 

def g(x, &block); end 
g(3) { 2+2 } # legal 

def h(x); end 
h(3) { 2+2 } # legal 

Đối với sử dụng sau này trong một hàm:

def x(&block) # x is a 0 param function 
    y(block)  # y is a 1 param function (taking one "Proc") 
    z(&block)  # z is a 0 param function (like x) with the block x received 
end 

Vì vậy, nếu bạn gọi z(&block) nó (gần !!) giống như gọi z { yield }: Bạn chỉ cần vượt qua khối chức năng tiếp theo.

Các vấn đề liên quan