คุณเคยเห็นฟังก์ชันที่ประกาศเช่นนี้หรือไม่?
def foo a, **b
  ...
end
ฉันเข้าใจว่าตัวเดียว*เป็นตัวดำเนินการสีแดง อะไร**หมายถึง?
คุณเคยเห็นฟังก์ชันที่ประกาศเช่นนี้หรือไม่?
def foo a, **b
  ...
end
ฉันเข้าใจว่าตัวเดียว*เป็นตัวดำเนินการสีแดง อะไร**หมายถึง?
คำตอบ:
Ruby 2.0 แนะนำอาร์กิวเมนต์คำหลักและ**ทำหน้าที่เหมือน*แต่สำหรับอาร์กิวเมนต์คำหลัก ส่งคืนแฮชที่มีคู่ของคีย์ / ค่า
สำหรับรหัสนี้:
def foo(a, *b, **c)
  [a, b, c]
end
นี่คือตัวอย่าง:
> 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}]
              นั่นคือโอเปอเรเตอร์สแลทคู่ที่มีให้ตั้งแต่ Ruby 2.0
มันรวบรวมอาร์กิวเมนต์ของคำหลักทั้งหมด(ซึ่งอาจเป็นแฮชแบบง่ายซึ่งเป็นวิธีที่ใช้ในการเลียนแบบการขัดแย้งของคำหลักก่อนที่จะกลายเป็นส่วนหนึ่งของภาษา Ruby)
def my_method(**options)
  puts options.inspect
end
my_method(key: "value")
โค้ดด้านบน{key:value}จะพิมพ์ไปที่คอนโซล
เช่นเดียวกับผู้ประกอบการเครื่องหมายเดียวจับข้อโต้แย้งปกติ แต่แทนที่จะเป็นอาร์เรย์คุณจะได้รับกัญชา
ตัวอย่างชีวิตจริง:
ตัวอย่างเช่นใน Rails cycleวิธีที่มีลักษณะเช่นนี้:
def cycle(first_value, *values)
  options = values.extract_options!
  # ...
end
วิธีการนี้สามารถเรียกได้ดังนี้: cycle("red", "green", "blue", name: "colors").
นี้ค่อนข้างรูปแบบทั่วไป: คุณยอมรับรายการของอาร์กิวเมนต์และสุดท้ายคือแฮตัวเลือกซึ่งสามารถเป็นสารสกัด - ตัวอย่างเช่น - ใช้ extract_options!ActiveSupport
ใน Ruby 2.0 คุณสามารถทำให้วิธีการเหล่านี้ง่ายขึ้น:
def cycle(first_value, *values, **options)
  # Same code as above without further changes!
end
เป็นที่ยอมรับว่าเป็นการปรับปรุงเล็กน้อยหากคุณใช้ ActiveSupport อยู่แล้ว แต่สำหรับ Ruby ธรรมดารหัสจะได้รับความกระชับค่อนข้างมาก
นอกจากนี้คุณสามารถใช้มันในฝั่งผู้โทรเช่นนี้:
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}แล้วfoo 10, opts, f: 60จะกำหนด{f: 60}ไปcในขณะที่จะกำหนดfoo 10, **opts, f: 60{d: 40, e: 50, f: 60}เพื่อให้ได้เอฟเฟกต์ที่สองก่อนหน้านี้คุณต้องมีmergeอาร์เรย์อย่างชัดเจน