คุณเคยเห็นฟังก์ชันที่ประกาศเช่นนี้หรือไม่?
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
อาร์เรย์อย่างชัดเจน