Apa yang dilakukan oleh operator ganda * (percikan)

214

Pernahkah Anda melihat fungsi yang dideklarasikan seperti ini?

def foo a, **b
  ...
end

Saya mengerti bahwa satu *adalah operator percikan. Apa **artinya

Roy Lee
sumber

Jawaban:

373

Ruby 2.0 memperkenalkan argumen kata kunci, dan **bertindak seperti *, tetapi untuk argumen kata kunci. Ini mengembalikan hash dengan pasangan kunci / nilai.

Untuk kode ini:

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

Ini 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}]
Dogbert
sumber
44
Ini menjawab pertanyaan dengan sempurna, tapi saya punya sedikit tambahan. Sama seperti operator percikan dapat digunakan pada array yang Anda lewati, percikan ganda dapat digunakan pada hashes. Jika opts = {d: 40, e: 50}, maka foo 10, opts, f: 60akan menetapkan {f: 60}ke c, sedangkan foo 10, **opts, f: 60akan menetapkan {d: 40, e: 50, f: 60}. Untuk mencapai efek kedua, sebelumnya Anda akan memiliki mergearray secara eksplisit.
brymck
Saya akan menganggap ini berguna untuk menetapkan parameter hash opsional untuk suatu metode
bigpotato
Mungkin patut dicatat bahwa jika mencampur argumen kata kunci dengan kata kunci percikan, kata kunci percikan perlu muncul setelah argumen kata kunci.
MrMesees
43

Itu adalah operator percikan ganda yang tersedia sejak Ruby 2.0.

Itu menangkap semua argumen kata kunci (yang juga bisa menjadi hash sederhana, yang merupakan cara idiomatis untuk meniru argumen kata kunci sebelum mereka menjadi bagian dari bahasa Ruby)

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

my_method(key: "value")

Kode di atas mencetak {key:value}ke konsol.

Sama seperti operator percikan tunggal menangkap semua argumen reguler, tetapi bukannya array Anda mendapatkan hash .

Contoh kehidupan nyata:

Sebagai contoh di Rails, cyclemetodenya terlihat seperti ini:

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

Metode ini bisa disebut seperti ini: cycle("red", "green", "blue", name: "colors").

Ini adalah pola yang cukup umum: Anda menerima daftar argumen dan yang terakhir adalah hash opsi, yang dapat diekstraksi - misalnya - menggunakan ActiveSupport extract_options!.

Di Ruby 2.0 Anda dapat menyederhanakan metode ini:

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

Memang ini hanya perbaikan kecil jika Anda sudah menggunakan ActiveSupport tetapi untuk Ruby biasa kode ini mendapatkan cukup banyak keringkasan.

Daniel Rikowski
sumber
20

Selain itu, Anda dapat menggunakannya di sisi pemanggil seperti ini:

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}
kuboon
sumber
5
Wow, double-splat analog dengan operator penyebaran objek ES6.
mpoisot
1
Terima kasih, itu konfirmasi yang saya cari.
Qortex