2013-08-17 31 views

Trả lời

276

Ruby 2.0 giới thiệu đối số từ khóa và ** hoạt động như *, nhưng đối với đối số từ khóa. Nó trả về một Hash với các cặp khóa/giá trị.

Đối với mã này:

def foo(a, *b, **c) 
    [a, b, c] 
end 

Dưới đây là một bản demo:

> foo 10 
=> [10, [], {}] 
> foo 10, 20, 30 
=> [10, [20, 30], {}] 
> foo 10, 20, 30, d: 40, e: 50 
=> [10, [20, 30], {:d=>40, :e=>50}] 
> foo 10, d: 40, e: 50 
=> [10, [], {:d=>40, :e=>50}] 
+32

này trả lời các câu hỏi hoàn hảo, nhưng tôi đã có một phụ lục nhỏ. Cũng giống như toán tử splat có thể được sử dụng trên mảng mà bạn truyền, thì double splat có thể được sử dụng trên các hash. Nếu 'opts = {d: 40, e: 50}', thì 'foo 10, opts, f: 60' sẽ gán' {f: 60} 'thành' c', trong khi 'foo 10, ** opts, f : 60' sẽ gán '{d: 40, e: 50, f: 60}'.Để đạt được hiệu ứng thứ hai, trước đây bạn sẽ có 'merge'd các mảng một cách rõ ràng. – brymck

+0

Tôi cho rằng điều này rất hữu ích cho việc thiết lập các tham số băm tùy chọn cho một phương thức – Edmund

+9

LƯU Ý: Nếu bạn sử dụng cấu trúc @ brymck (ít nhất là trong MRI Ruby 2.1.1), hành vi không phải là 'hợp nhất' nhưng' hợp nhất! '- nghĩa là, 'opts' bây giờ sẽ là' {d: 40, e: 50, f: 60} '. Tuy nhiên, điều này là không đúng, nếu bạn đảo ngược các đối số - tức là, 'foo 10, c: 30, ** opts' sẽ KHÔNG thêm vĩnh viễn' c: 30' vào 'opts'. Tôi chưa thấy bất kỳ tài liệu nào liên quan đến hành vi này, và tôi thấy nó rất đáng ngạc nhiên. –

30

Đó là splat đôi điều hành trong đó có sẵn từ của Ruby 2.0.

Nó nắm bắt tất cả đối số từ khóa (mà cũng có thể là một băm đơn giản, đó là cách thành ngữ để thi đua đối số từ khóa trước khi họ trở thành một phần của ngôn ngữ Ruby)

def my_method(**options) 
    puts options.inspect 
end 

my_method(key: "value") 

Các bản in mã trên {key:value} vào bảng điều khiển.

Giống như nhà điều hành mạng đơn lẻ chụp tất cả các đối số thông thường, nhưng thay vì một mảng bạn nhận được băm.

Cuộc sống thực ví dụ:

Ví dụ trong Rails phương pháp cycle trông như thế này:

def cycle(first_value, *values) 
    options = values.extract_options! 
    # ... 
end 

Phương pháp này có thể được gọi như thế này: cycle("red", "green", "blue", name: "colors").

Đây là mẫu khá phổ biến: Bạn chấp nhận danh sách các đối số và giá trị cuối cùng là băm tùy chọn, có thể trích xuất - ví dụ - sử dụng số extract_options! của ActiveSupport.

Trong Ruby 2.0, bạn có thể đơn giản hóa các phương pháp:

def cycle(first_value, *values, **options) 
    # Same code as above without further changes! 
end 

Phải thừa nhận rằng nó chỉ là một sự cải thiện nhỏ nếu bạn đang sử dụng ActiveSupport nhưng đối với đồng bằng Ruby tăng đang khá nhiều conciseness.

-16

Đối với số nguyên, ** nghĩa mũ tức là 2 ** 3 cũng giống như 2^3

+1

'^' là nhị phân XOR trong ruby, vì vậy '2^3! = 2 ** 3' nhưng '2^3 == 1' – yurko

+5

Dường như không liên quan đến câu hỏi. –

6

Bên cạnh đó, bạn có thể sử dụng nó ở bên người gọi như thế này:

def foo(opts); p opts end 
bar = {a:1, b:2} 

foo(bar, c: 3) 
=> ArgumentError: wrong number of arguments (given 2, expected 1) 

foo(**bar, c: 3) 
=> {:a=>1, :b=>2, :c=>3}