Array slicing ใน Ruby: คำอธิบายสำหรับพฤติกรรมไร้เหตุผล (นำมาจาก Rubykoans.com)


232

ฉันกำลังทำแบบฝึกหัดในRuby Koansและฉันรู้สึกประหลาดกับการเล่นโวหารของทับทิมต่อไปนี้ซึ่งฉันพบว่าไม่สามารถอธิบายได้จริงๆ:

array = [:peanut, :butter, :and, :jelly]

array[0]     #=> :peanut    #OK!
array[0,1]   #=> [:peanut]  #OK!
array[0,2]   #=> [:peanut, :butter]  #OK!
array[0,0]   #=> []    #OK!
array[2]     #=> :and  #OK!
array[2,2]   #=> [:and, :jelly]  #OK!
array[2,20]  #=> [:and, :jelly]  #OK!
array[4]     #=> nil  #OK!
array[4,0]   #=> []   #HUH??  Why's that?
array[4,100] #=> []   #Still HUH, but consistent with previous one
array[5]     #=> nil  #consistent with array[4] #=> nil  
array[5,0]   #=> nil  #WOW.  Now I don't understand anything anymore...

ดังนั้นทำไมเป็น array[5,0]ไม่เท่ากับarray[4,0]? มีเหตุผลใดที่การแบ่งส่วนข้อมูลมีพฤติกรรมแบบนี้แปลก ๆ เมื่อคุณเริ่มต้นที่ตำแหน่ง (ความยาว + 1) ตำแหน่งth ?



ดูเหมือนว่าหมายเลขแรกคือดัชนีที่จะเริ่มต้น, หมายเลขที่สองคือจำนวนองค์ประกอบที่จะเชือด
ออสติน

คำตอบ:


185

การแบ่งส่วนและการจัดทำดัชนีเป็นการดำเนินการที่แตกต่างกันสองแบบและการอนุมานพฤติกรรมของอันหนึ่งจากอีกอันหนึ่งคือปัญหาของคุณ

อาร์กิวเมนต์แรกในชิ้นระบุไม่องค์ประกอบ แต่สถานที่ระหว่างองค์ประกอบกำหนดช่วง (และไม่องค์ประกอบตัวเอง):

  :peanut   :butter   :and   :jelly
0         1         2      3        4

4 ยังคงอยู่ในอาเรย์ หากคุณร้องขอองค์ประกอบ 0 รายการคุณจะได้รับจุดสิ้นสุดว่างของอาร์เรย์ แต่ไม่มีดัชนี 5 ดังนั้นคุณจึงไม่สามารถแบ่งได้

เมื่อคุณทำดัชนี (เช่นarray[4]) คุณจะชี้ไปที่องค์ประกอบต่างๆดังนั้นดัชนีจะเริ่มจาก 0 ถึง 3 เท่านั้น


8
เป็นการคาดเดาที่ดีเว้นแต่จะมีการสำรองข้อมูลโดยแหล่งที่มา ฉันจะสนใจในลิงค์ถ้ามีเพียงเพื่ออธิบาย "ทำไม" เช่น OP และผู้แสดงความคิดเห็นคนอื่น ๆ กำลังถาม ไดอะแกรมของคุณสมเหตุสมผลแล้วยกเว้น Array [4] เป็นศูนย์ Array [3] คือ: jelly ฉันคาดหวังว่า Array [4, N] จะว่างเปล่า แต่มัน [] เหมือนที่ OP บอก หากเป็นสถานที่มันเป็นสถานที่ที่ไร้ประโยชน์เพราะ Array [4, -1] ไม่มีค่า ดังนั้นคุณไม่สามารถทำอะไรกับ Array [4]
squarism

5
@quarism ฉันเพิ่งได้รับการยืนยันจาก Charles Oliver Nutter (@headius บน Twitter) ว่านี่เป็นคำอธิบายที่ถูกต้อง เขาเป็นนักพัฒนา JRuby ครั้งใหญ่ดังนั้นฉันจึงคิดว่าคำพูดของเขาน่าเชื่อถือ
แฮงค์เกย์

18
ต่อไปนี้คือข้ออ้างสำหรับพฤติกรรมนี้: blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/380637
Matt Briançon

4
คำอธิบายที่ถูกต้อง การสนทนาที่คล้ายกันใน ruby-core: redmine.ruby-lang.org/issues/4245 , redmine.ruby-lang.org/issues/4541
Marc-André Lafortune

18
เรียกอีกอย่างว่า "การโพสต์รั้ว" มีรั้วโพสต์ที่ห้า (id 4) อยู่ แต่องค์ประกอบที่ห้าไม่มี การแบ่งส่วนเป็นการดำเนินการโพสต์รั้วการทำดัชนีเป็นการดำเนินงานองค์ประกอบ
Matty K

27

สิ่งนี้เกี่ยวข้องกับข้อเท็จจริงที่ว่าชิ้นส่งคืนอาร์เรย์เอกสารแหล่งข้อมูลที่เกี่ยวข้องจาก Array # slice:

 *  call-seq:
 *     array[index]                -> obj      or nil
 *     array[start, length]        -> an_array or nil
 *     array[range]                -> an_array or nil
 *     array.slice(index)          -> obj      or nil
 *     array.slice(start, length)  -> an_array or nil
 *     array.slice(range)          -> an_array or nil

ซึ่งแสดงให้ฉันเห็นว่าถ้าคุณให้การเริ่มต้นที่ไม่มีขอบเขตมันจะคืนค่าศูนย์ดังนั้นในตัวอย่างของคุณarray[4,0]จะขอองค์ประกอบที่ 4 ที่มีอยู่ แต่ขอให้ส่งกลับอาร์เรย์ขององค์ประกอบศูนย์ ในขณะที่array[5,0]ขอดัชนีออกจากขอบเขตดังนั้นมันจะส่งกลับศูนย์ นี่อาจเหมาะสมกว่าถ้าคุณจำได้ว่าวิธีการแบ่งส่วนส่งคืนอาร์เรย์ใหม่ไม่ใช่การเปลี่ยนแปลงโครงสร้างข้อมูลดั้งเดิม

แก้ไข:

หลังจากตรวจสอบความคิดเห็นฉันตัดสินใจที่จะแก้ไขคำตอบนี้ Slice เรียกใช้ข้อมูลโค้ดต่อไปนี้เมื่อค่า arg เป็นสอง:

if (argc == 2) {
    if (SYMBOL_P(argv[0])) {
        rb_raise(rb_eTypeError, "Symbol as array index");
    }
    beg = NUM2LONG(argv[0]);
    len = NUM2LONG(argv[1]);
    if (beg < 0) {
        beg += RARRAY(ary)->len;
    }
    return rb_ary_subseq(ary, beg, len);
}

ถ้าคุณดูในarray.cคลาสที่กำหนดrb_ary_subseqเมธอดคุณจะเห็นว่ามันจะคืนค่าศูนย์ถ้าความยาวไม่เกินขอบเขตไม่ใช่ดัชนี:

if (beg > RARRAY_LEN(ary)) return Qnil;

ในกรณีนี้นี่คือสิ่งที่เกิดขึ้นเมื่อมีการส่งผ่าน 4 มันจะตรวจสอบว่ามี 4 องค์ประกอบและจึงไม่ก่อให้เกิดการส่งกลับศูนย์ จากนั้นจะดำเนินการต่อและส่งคืนอาร์เรย์ว่างถ้า arg ที่สองถูกตั้งค่าเป็นศูนย์ ในขณะที่ถ้าผ่าน 5 เข้าไปจะไม่มีองค์ประกอบ 5 ตัวในอาเรย์ดังนั้นมันจะคืนค่าศูนย์ก่อนที่จะมีการประเมินค่าหาค่าศูนย์หาค่า รหัสที่นี่ที่บรรทัด 944

ฉันเชื่อว่านี่เป็นข้อผิดพลาดหรืออย่างน้อยก็คาดเดาไม่ได้และไม่ใช่ 'หลักการแห่งความประหลาดใจอย่างน้อย' เมื่อฉันได้รับไม่กี่นาทีฉันจะส่งแพทช์ทดสอบที่ล้มเหลวให้กับทับทิมอย่างน้อยที่สุด


2
แต่ ... องค์ประกอบที่ระบุโดย 4 ในอาร์เรย์ [4,0] ไม่มีอยู่ ... - เพราะจริงๆแล้วมันเป็นองค์ประกอบ 5 (การนับ 0 ตามดูตัวอย่าง) ดังนั้นมันจึงอยู่นอกขอบเขตเช่นกัน
Pascal Van Hecke

1
คุณถูก. ฉันกลับไปดูที่แหล่งที่มาและดูเหมือนว่าอาร์กิวเมนต์แรกจะถูกจัดการภายในรหัส c เป็นความยาวไม่ใช่ดัชนี ฉันจะแก้ไขคำตอบของฉันเพื่อสะท้อนสิ่งนี้ ฉันคิดว่านี่อาจเป็นข้อผิดพลาด
Jed Schneider

23

อย่างน้อยโปรดทราบว่าพฤติกรรมนั้นสอดคล้องกัน จาก 5 ขึ้นไปทุกอย่างทำหน้าที่เหมือนกัน; [4,N]ความแปลกประหลาดเกิดขึ้นเฉพาะที่

บางทีรูปแบบนี้อาจช่วยได้หรือบางทีฉันแค่เหนื่อยและไม่ได้ช่วยอะไรเลย

array[0,4] => [:peanut, :butter, :and, :jelly]
array[1,3] => [:butter, :and, :jelly]
array[2,2] => [:and, :jelly]
array[3,1] => [:jelly]
array[4,0] => []

ที่[4,0]เราพบจุดสิ้นสุดของอาร์เรย์ nilที่จริงผมพบว่ามันค่อนข้างแปลกเท่าที่ความงามในรูปแบบไปหากคนสุดท้ายกลับ เนื่องจากบริบทเช่นนี้4เป็นตัวเลือกที่ยอมรับได้สำหรับพารามิเตอร์แรกเพื่อให้สามารถส่งคืนอาร์เรย์ว่างได้ เมื่อเราตี 5 ขึ้นไปวิธีการที่น่าจะออกมาทันทีโดยธรรมชาติของการถูกทั้งหมดและออกจากขอบเขตอย่างสมบูรณ์


12

สิ่งนี้เหมาะสมเมื่อคุณพิจารณาว่าการแบ่งอาร์เรย์อาจเป็นค่า lvalue ที่ถูกต้องไม่ใช่เฉพาะค่า rvalue:

array = [:peanut, :butter, :and, :jelly]
# replace 0 elements starting at index 5 (insert at end or array):
array[4,0] = [:sandwich]
# replace 0 elements starting at index 0 (insert at head of array):
array[0,0] = [:make, :me, :a]
# array is [:make, :me, :a, :peanut, :butter, :and, :jelly, :sandwich]

# this is just like replacing existing elements:
array[3, 4] = [:grilled, :cheese]
# array is [:make, :me, :a, :grilled, :cheese, :sandwich]

นี้จะไม่เป็นไปได้ถ้าarray[4,0]กลับมาแทนnil []อย่างไรก็ตามการarray[5,0]ส่งคืนnilเนื่องจากเกินขอบเขต (การแทรกหลังจากองค์ประกอบที่ 4 ของอาร์เรย์ 4 องค์ประกอบมีความหมาย แต่การแทรกหลังจากองค์ประกอบที่ 5 ของอาร์เรย์องค์ประกอบ 4 ไม่ใช่)

อ่านไวยากรณ์ชิ้นarray[x,y]เป็น "เริ่มต้นหลังจากxองค์ประกอบในarrayเลือกได้ถึงyองค์ประกอบ" สิ่งนี้มีความหมายก็ต่อเมื่อarrayมีxองค์ประกอบอย่างน้อย


11

นี้ไม่เข้าท่า

คุณต้องสามารถกำหนดให้กับส่วนเหล่านั้นดังนั้นจึงกำหนดไว้ในลักษณะที่จุดเริ่มต้นและจุดสิ้นสุดของสตริงมีนิพจน์ที่มีความยาวเป็นศูนย์

array[4, 0] = :sandwich
array[0, 0] = :crunchy
=> [:crunchy, :peanut, :butter, :and, :jelly, :sandwich]

1
คุณยังสามารถกำหนดให้กับช่วงที่ชิ้นที่ส่งคืนเป็นศูนย์ดังนั้นมันจะมีประโยชน์ในการขยายคำอธิบายนี้ array[5,0]=:foo # array is now [:peanut, :butter, :and, :jelly, nil, :foo]
mfazekas

หมายเลขที่สองทำอะไรเมื่อกำหนด ดูเหมือนว่าจะถูกละเว้น [26] pry(main)> array[4,5] = [:love, :hope, :peace] => [:peanut, :butter, :and, :jelly, :love, :hope, :peace]
Drew Verlee

@drewverlee ไม่ได้สนใจ:array = [:a, :b, :c, :d, :e]; array[1,2] = :x, :x; array => [:a, :x, :x, :d, :e]
fanaugen

10

ฉันพบคำอธิบายโดย Gary Wright ที่เป็นประโยชน์เช่นกัน http://www.ruby-forum.com/topic/1393096#990065

คำตอบของ Gary Wright คือ -

http://www.ruby-doc.org/core/classes/Array.html

เอกสารชัดเจนยิ่งขึ้น แต่พฤติกรรมที่แท้จริงนั้นสอดคล้องกับตนเองและมีประโยชน์ หมายเหตุ: ฉันสมมติว่ารุ่น String 1.9.X

ช่วยในการพิจารณาการกำหนดหมายเลขด้วยวิธีต่อไปนี้:

  -4  -3  -2  -1    <-- numbering for single argument indexing
   0   1   2   3
 +---+---+---+---+
 | a | b | c | d |
 +---+---+---+---+
 0   1   2   3   4  <-- numbering for two argument indexing or start of range
-4  -3  -2  -1

ข้อผิดพลาดทั่วไป (และเข้าใจได้) นั้นถือว่าเกินไปว่าซีแมนทิกส์ของดัชนีอาร์กิวเมนต์เดียวนั้นเหมือนกับความหมายของ อาร์กิวเมนต์แรกในสถานการณ์สมมติอาร์กิวเมนต์สองรายการ (หรือช่วง) มันไม่เหมือนกันในทางปฏิบัติและเอกสารไม่ได้สะท้อนสิ่งนี้ แม้ว่าข้อผิดพลาดนั้นแน่นอนในเอกสารประกอบและไม่ใช่ในการนำไปใช้งาน:

อาร์กิวเมนต์เดียว: ดัชนีแสดงถึงตำแหน่งอักขระเดียวภายในสตริง ผลลัพธ์เป็นสตริงอักขระเดี่ยวที่พบที่ดัชนีหรือไม่มีเนื่องจากไม่มีอักขระที่ดัชนีที่กำหนด

  s = ""
  s[0]    # nil because no character at that position

  s = "abcd"
  s[0]    # "a"
  s[-4]   # "a"
  s[-5]   # nil, no characters before the first one

อาร์กิวเมนต์จำนวนเต็มสองข้อ: อาร์กิวเมนต์ระบุส่วนของสตริงที่ต้องการแยกหรือแทนที่ โดยเฉพาะอย่างยิ่งส่วนที่มีความกว้างเป็นศูนย์ของสตริงสามารถระบุได้เพื่อให้สามารถแทรกข้อความก่อนหรือหลังอักขระที่มีอยู่ซึ่งรวมถึงที่ด้านหน้าหรือท้ายของสตริง ในกรณีนี้อาร์กิวเมนต์แรกไม่ได้ระบุตำแหน่งของอักขระ แต่จะระบุช่องว่างระหว่างอักขระตามที่แสดงในแผนภาพด้านบนแทน อาร์กิวเมนต์ที่สองคือความยาวซึ่งสามารถเป็น 0

s = "abcd"   # each example below assumes s is reset to "abcd"

To insert text before 'a':   s[0,0] = "X"           #  "Xabcd"
To insert text after 'd':    s[4,0] = "Z"           #  "abcdZ"
To replace first two characters: s[0,2] = "AB"      #  "ABcd"
To replace last two characters:  s[-2,2] = "CD"     #  "abCD"
To replace middle two characters: s[1..3] = "XX"    #  "aXXd"

พฤติกรรมของช่วงนั้นค่อนข้างน่าสนใจ จุดเริ่มต้นเป็นเช่นเดียวกับอาร์กิวเมนต์แรกเมื่อมีการให้สองอาร์กิวเมนต์ (ตามที่อธิบายข้างต้น) แต่จุดสิ้นสุดของช่วงสามารถเป็น 'ตำแหน่งอักขระ' เช่นเดียวกับการจัดทำดัชนีเดียวหรือ "ตำแหน่งขอบ" เช่นเดียวกับอาร์กิวเมนต์จำนวนเต็มสองตัว ความแตกต่างนั้นพิจารณาจากการใช้ช่วงจุดสองจุดหรือจุดสามจุด:

s = "abcd"
s[1..1]           # "b"
s[1..1] = "X"     # "aXcd"

s[1...1]          # ""
s[1...1] = "X"    # "aXbcd", the range specifies a zero-width portion of
the string

s[1..3]           # "bcd"
s[1..3] = "X"     # "aX",  positions 1, 2, and 3 are replaced.

s[1...3]          # "bc"
s[1...3] = "X"    # "aXd", positions 1, 2, but not quite 3 are replaced.

หากคุณย้อนกลับไปดูตัวอย่างเหล่านี้และยืนยันและใช้ซีแมนทิกส์ดัชนีเดียวสำหรับตัวอย่างการจัดทำดัชนีแบบดับเบิลหรือช่วงคุณจะสับสน คุณต้องใช้เลขลำดับที่ฉันแสดงในไดอะแกรม Ascii เพื่อจำลองพฤติกรรมที่แท้จริง


3
คุณสามารถรวมแนวคิดหลักของเธรดนั้นได้หรือไม่? (ในกรณีของการเชื่อมโยงวันหนึ่งจะไม่ถูกต้อง)
VonC

8

ฉันยอมรับว่าสิ่งนี้ดูเหมือนว่าพฤติกรรมแปลก ๆ แต่แม้กระทั่งเอกสารอย่างเป็นทางการเกี่ยวกับการArray#sliceแสดงพฤติกรรมเช่นเดียวกับในตัวอย่างของคุณใน "กรณีพิเศษ" ด้านล่าง:

   a = [ "a", "b", "c", "d", "e" ]
   a[2] +  a[0] + a[1]    #=> "cab"
   a[6]                   #=> nil
   a[1, 2]                #=> [ "b", "c" ]
   a[1..3]                #=> [ "b", "c", "d" ]
   a[4..7]                #=> [ "e" ]
   a[6..10]               #=> nil
   a[-3, 3]               #=> [ "c", "d", "e" ]
   # special cases
   a[5]                   #=> nil
   a[5, 1]                #=> []
   a[5..10]               #=> []

น่าเสียดายที่คำอธิบายของพวกเขาArray#sliceดูเหมือนจะไม่ได้ให้ข้อมูลเชิงลึกเกี่ยวกับสาเหตุที่ใช้งานวิธีนี้:

องค์ประกอบการอ้างอิงผลตอบแทนองค์ประกอบที่ดัชนีหรือผลตอบแทน subarray เริ่มต้นที่จุดเริ่มต้น และต่อเนื่องสำหรับระยะเวลาใน องค์ประกอบหรือผลตอบแทน subarray ที่ระบุโดยช่วง ดัชนีลบนับถอยหลังจากจุดสิ้นสุดของอาร์เรย์ (-1 คือองค์ประกอบสุดท้าย) ส่งคืนศูนย์ถ้าดัชนี (หรือดัชนีเริ่มต้น) อยู่นอกช่วง


7

คำอธิบายโดยJim Weirich

วิธีหนึ่งที่จะคิดเกี่ยวกับมันคือตำแหน่งดัชนี 4 อยู่ที่ขอบของอาเรย์ เมื่อขอชิ้นคุณจะกลับมาเป็นอาร์เรย์ที่เหลือ ดังนั้นให้พิจารณาอาร์เรย์ [2,10], อาร์เรย์ [3,10] และอาร์เรย์ [4,10] ... แต่ละคืนบิตที่เหลือของจุดสิ้นสุดของอาร์เรย์: 2 องค์ประกอบ 1 องค์ประกอบและ 1 องค์ประกอบตามลำดับ อย่างไรก็ตามตำแหน่งที่ 5 นั้นอยู่นอกอาเรย์อย่างชัดเจนและไม่อยู่ที่ขอบดังนั้นอาเรย์ [5,10] จะส่งกลับค่าศูนย์


6

พิจารณาอาร์เรย์ต่อไปนี้:

>> array=["a","b","c"]
=> ["a", "b", "c"]

คุณสามารถแทรกรายการไปยังจุดเริ่มต้น (หัว) a[0,0]ของอาร์เรย์โดยการกำหนดให้มัน ที่จะนำองค์ประกอบระหว่าง"a"และการใช้งาน"b" a[1,0]โดยทั่วไปในสัญกรณ์a[i,n], iหมายถึงดัชนีและnจำนวนขององค์ประกอบ เมื่อn=0มันกำหนดตำแหน่งระหว่างองค์ประกอบของอาร์เรย์

ตอนนี้ถ้าคุณคิดถึงจุดสิ้นสุดของอาร์เรย์คุณจะสามารถผนวกรายการต่อท้ายได้อย่างไรโดยใช้สัญลักษณ์ที่อธิบายไว้ข้างต้น a[3,0]ง่ายกำหนดค่าให้ นี่คือส่วนท้ายของอาร์เรย์

ดังนั้นถ้าคุณพยายามที่จะเข้าถึงองค์ประกอบที่คุณจะได้รับa[3,0] []ในกรณีนี้คุณยังคงอยู่ในช่วงของอาร์เรย์ แต่ถ้าคุณพยายามเข้าถึงa[4,0]คุณจะได้รับnilค่าตอบแทนเนื่องจากคุณไม่ได้อยู่ในช่วงของอาร์เรย์อีกต่อไป

อ่านข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ที่http://mybrainstormings.wordpress.com/2012/09/10/arrays-in-ruby/


0

tl; dr: ในซอร์สโค้ดarray.cฟังก์ชั่นที่แตกต่างกันจะถูกเรียกขึ้นอยู่กับว่าคุณผ่าน 1 หรือ 2 ข้อโต้แย้งในการArray#sliceทำให้เกิดผลตอบแทนที่ไม่คาดคิด

(ก่อนอื่นฉันอยากจะชี้ให้เห็นว่าฉันไม่ได้ใช้รหัสใน C แต่ใช้ Ruby มาหลายปีดังนั้นถ้าคุณไม่คุ้นเคยกับ C แต่คุณใช้เวลาสักครู่เพื่อทำความคุ้นเคยกับพื้นฐาน ฟังก์ชั่นและตัวแปรมันไม่ยากที่จะติดตามซอร์สโค้ด Ruby ดังที่แสดงไว้ด้านล่างคำตอบนี้ใช้ Ruby v2.3 แต่กลับเหมือนเดิมมากไปหรือน้อยกว่า v1.9)

สถานการณ์ # 1

array.length == 4; array.slice(4) #=> nil

หากคุณดูซอร์สโค้ดสำหรับArray#slice( rb_ary_aref) คุณจะเห็นว่าเมื่อมีการส่งอาร์กิวเมนต์เพียงหนึ่งรายการเท่านั้น ( บรรทัด 1277-1289 ) rb_ary_entryจะถูกส่งผ่านไปยังค่าดัชนี (ซึ่งอาจเป็นค่าบวกหรือลบ)

rb_ary_entryจากนั้นคำนวณตำแหน่งขององค์ประกอบที่ร้องขอจากจุดเริ่มต้นของอาร์เรย์ (กล่าวอีกนัยหนึ่งถ้าดัชนีลบส่งผ่านเข้ามาจะคำนวณค่าบวกที่เทียบเท่า) แล้วเรียกrb_ary_eltให้รับองค์ประกอบที่ร้องขอ

เป็นที่คาดหวังrb_ary_eltผลตอบแทนnilเมื่อความยาวของอาร์เรย์lenคือน้อยกว่าหรือเท่ากับดัชนี (ที่นี่เรียกว่าoffset)

1189:  if (offset < 0 || len <= offset) {
1190:    return Qnil;
1191:  } 

สถานการณ์ # 2

array.length == 4; array.slice(4, 0) #=> []

อย่างไรก็ตามเมื่อมีการส่งผ่าน 2 อาร์กิวเมนต์ (เช่นดัชนีเริ่มต้นbegและความยาวของชิ้นlen) rb_ary_subseqจะถูกเรียก

ในrb_ary_subseqถ้าดัชนีเริ่มต้นbegเป็นมากกว่าความยาวอาร์เรย์alen, nilจะถูกส่งกลับ:

1208:  long alen = RARRAY_LEN(ary);
1209:
1210:  if (beg > alen) return Qnil;

มิฉะนั้นความยาวของชิ้นส่วนที่ได้lenจะถูกคำนวณและถ้ามันถูกกำหนดให้เป็นศูนย์จะส่งคืนอาร์เรย์ว่างเปล่า:

1213:  if (alen < len || alen < beg + len) {
1214:  len = alen - beg;
1215:  }
1216:  klass = rb_obj_class(ary);
1217:  if (len == 0) return ary_new(klass, 0);

ดังนั้นเนื่องจากดัชนีเริ่มต้นของ 4 ไม่มากกว่าarray.lengthอาร์เรย์ว่างจะถูกส่งกลับแทนnilค่าที่หนึ่งอาจคาดหวัง

ตอบคำถามแล้ว?

หากคำถามจริงที่นี่ไม่ใช่ "รหัสอะไรที่ทำให้สิ่งนี้เกิดขึ้น?" แต่ "ทำไม Matz ถึงทำแบบนี้?" คุณต้องซื้อกาแฟให้เขาที่ RubyConf ในครั้งต่อไปและ ถามเขา.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.