Câu trả lời:
Ruby 2.0 đã giới thiệu các đối số từ khóa và **
hoạt động như thế *
, nhưng đối với các đố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
Đây là 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}]
Đó là toán tử splat kép có sẵn kể từ Ruby 2.0.
Nó nắm bắt tất cả các đối số từ khóa (cũng có thể là một hàm băm đơn giản, đó là cách thành ngữ để mô phỏng các đối số từ khóa trước khi chúng 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 mã trên in {key:value}
ra bàn điều khiển.
Giống như toán tử splat duy nhất nắm bắt tất cả các đối số thông thường, nhưng thay vì một mảng, bạn nhận được một hàm băm .
Ví dụ thực tế:
Ví dụ trong Rails, cycle
phương thức 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ột mẫu khá phổ biến: Bạn chấp nhận một danh sách các đối số và cái cuối cùng là hàm băm tùy chọn, có thể được trích xuất - ví dụ - sử dụng ActiveSupport extract_options!
.
Trong Ruby 2.0, bạn có thể đơn giản hóa các phương thức sau:
def cycle(first_value, *values, **options)
# Same code as above without further changes!
end
Phải thừa nhận rằng đó chỉ là một cải tiến nhỏ nếu bạn đang sử dụng ActiveSupport nhưng đối với Ruby đơn giản, mã đạt được khá nhiều sự đồng nhất.
Ngoài ra, bạn có thể sử dụng nó trong phía 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}
opts = {d: 40, e: 50}
, sau đófoo 10, opts, f: 60
sẽ gán{f: 60}
choc
, trong khifoo 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 rõ ràng.