ฉันสามารถเรียกวิธีการใด ๆ เกี่ยวกับศูนย์และสิ่งนี้รู้สึกผิด


14

ฉันใช้เวลามากในการดีบักสคริปต์เมื่อเร็ว ๆ นี้และเมื่อฉันพบปัญหาในที่สุดมันเป็นเพราะโค้ดที่มีลักษณะดังนี้:

class Foo {
    has $.bar;
    method () {
        # do stuff
        $!.bar;
    }
}

มันกลับกลายเป็นปัญหาอยู่กับที่$!.barซึ่งควรจะได้รับอย่างใดอย่างหนึ่งหรือ$!bar $.barฉันได้รับสิ่งนี้

แต่ทำไมไม่ตาย ?

กำลังมองหาที่นี้ในรายละเอียดมากขึ้นก็ดูเหมือนว่าปัญหาที่นี่เป็นที่ที่ฉันพยายามที่จะเรียก (ที่ไม่มีอยู่จริง) วิธีการbarใน$!ซึ่งในจุดนี้เป็นNilเพราะมียังไม่ได้รับข้อผิดพลาดใด ๆ

และดูเหมือนว่าที่จริงผมสามารถเรียกวิธีการใด ๆ ที่ฉันต้องการบนNilและพวกเขาทั้งหมดกลับมาเงียบ ๆNilรวมทั้งสิ่งที่ชอบและNil.this-is-a-fake-methodNil.reverse-entropy(123)

นี่เป็นคุณสมบัติหรือไม่? ถ้าเป็นเช่นนั้นมีเหตุผลอะไร?

คำตอบ:


13

มันตั้งใจและทำเป็นเอกสารใช่ พาดหัวสำหรับNilคือ "การขาดค่าหรือความล้มเหลวที่เป็นพิษเป็นภัย" และเอกสารประกอบการเรียนกล่าวถึง

การเรียกวิธีการเกี่ยวกับNilวิธีการที่ไม่ได้อยู่และดังนั้นการดำเนินการใด ๆ subscripting Nilจะประสบความสำเร็จและผลตอบแทน

say Nil.ITotallyJustMadeThisUp;  # OUTPUT: «Nil␤» 
say (Nil)[100];                  # OUTPUT: «Nil␤» 
say (Nil){100};                  # OUTPUT: «Nil␤»

บทสรุป 2ระบุว่า "การเรียกใช้เมธอดที่ไม่ได้กำหนดใด ๆNilส่งคืนNilดังนั้นNilการแพร่กระจายของเมธอดการเรียกเมธอดในทำนองเดียวกันการดำเนินการห้อยใด ๆ ในการNilส่งคืนNil" ดังนั้นเจตนาที่ดูเหมือนว่าจะอนุญาตให้ใช้นิพจน์เช่น$foo.Bar()[0].Baz()โดยไม่ต้องตรวจสอบNilทุกขั้นตอน "การเรียกใช้เมธอดและตัวดำเนินการตัวห้อย


4
จริง และค่อนข้างนานมาแล้วเช่นกัน: github.com/rakudo/rakudo/commit/174727377f (ธันวาคม 2013) ดูการเก็งกำไรที่เกี่ยวข้อง: design.raku.org/S02.html#Nil
Elizabeth Mattijsen

1
@ElizabethMattijsen อ่าฉันคิดว่า S02 มีคำตอบ "การเรียกใช้เมธอดที่ไม่ได้กำหนดใด ๆNilจะส่งคืนNilดังนั้นNilการแพร่กระจายของโซ่การเรียกใช้เมธอด" ดังนั้นจึงตั้งใจว่าคุณสามารถทำได้$foo.Bar().Baz().Blah()โดยไม่จำเป็นต้องทำการทดสอบศูนย์ในทุกขั้นตอนหรือ?.ตัวดำเนินการแบบพิเศษ(ตราบใดที่คุณจัดการศูนย์อย่างถูกต้องในตอนท้าย) ฉันจะแก้ไขสิ่งนั้นในขอบคุณ
ฮอบส์

1
A Nilที่ไม่ผิดพลาดและเพิ่งกลับมาNilใช้งานได้ค่อนข้างกว้างขวางใน Obj-C และ NS Frameworks ที่ใช้ในลักษณะที่คล้ายกัน - อนุญาตสำหรับการโทรที่ถูกล่ามโซ่ที่ส่งผ่านไปยังศูนย์ ฉันไม่ทราบถึงการลงโทษที่แน่นอนของข้อยกเว้นและการจับพวกเขา แต่ฉันเดาว่าการNilผูกมัดอาจมีประสิทธิภาพมากกว่าหากยืดหยุ่นน้อยกว่า
0721090601

1
(แต่นั่นเป็นการคาดเดาที่ไม่รู้ทั้งหมดดังนั้นฉันดีใจที่ lizmat หรือ jnthn บอกฉันว่าฉันผิดและต้องปิด :-))
user0721090601

2
Nilชั้นมีFALLBACK docs.raku.org/language/typesystem#index-entry-FALLBACK_(method)Nilวิธีการซึ่งผลตอบแทน โดยทั่วไปก่อนจะเกิดข้อผิดพลาดเนื่องจากไม่พบวิธีการตรวจสอบFALLBACKจะทำและเรียกใช้ถ้ามี
Elizabeth Mattijsen

5

คำถามนี้ (และคำตอบของฮอบส์) นอกจากนี้ยังทำให้ฉันรู้สึกไม่สบายใจ ... : ฉันในที่สุดก็พบhttps://docs.raku.org/language/traps : อธิบายมอบหมายที่ก่อให้เกิดความคุ้มค่าที่แตกต่างกันมักจะNil Anyการตอบสนอง REPL พื้นฐานต่อไปนี้แสดงให้เห็นถึงสิ่งนี้:

> my $foo = Nil
(Any)

> $foo.bar
No such method 'bar' for invocant of type 'Any'
  in block <unit> at <unknown file> line 1

> my $bar := Nil
Nil

> $bar.baz
Nil

((ความแตกต่างระหว่าง=และ:=ครอบคลุมอยู่ที่นี่: https://docs.raku.org/language/containers#Binding ))

... ดังนั้นความคิดทั่วไปคือ 'ค่าที่ขาดหายไปหรือความล้มเหลวที่เป็นพิษเป็นภัย' นั้นแพร่หลายน้อยกว่าในรหัสปกติมากกว่าฉัน (และบางทีคุณก็เป็นอย่างนั้นเหรอ?) ก็กลัวอย่างฉับพลัน: มันเกิดขึ้นอย่างไรก็ตามเมื่อคุณจะทำงานกับ regex ตรงโดยตรง$!และอยู่ในสถานการณ์อุบัติเหตุของคุณโดยเฉพาะที่เกี่ยวข้องกับวิธีการโดยตรงในการเรียก

สิ่งนี้ทำให้ฉันรู้มากขึ้นเกี่ยวกับความแตกต่างระหว่างNilและAnyและเหตุผลที่ให้ไว้ทำให้ฉันมีเหตุผลมากขึ้น


2
Nilตั้งค่าคอนเทนเนอร์เป็นสถานะเริ่มต้น คุณสามารถเปลี่ยนค่าเริ่มต้น my $foo is default(42) = 5; $foo = Nil; say $foo; # 42
แบรดกิลเบิร์ต
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.