เหตุใดจึงไม่มีการแปลงโดยนัย


14

ดังที่ฉันเข้าใจแล้วการแปลงโดยนัยอาจทำให้เกิดข้อผิดพลาด

แต่นั่นไม่สมเหตุสมผล - การแปลงปกติไม่ควรทำให้เกิดข้อผิดพลาดเช่นกัน?

ทำไมไม่มี

len(100)

ทำงานโดยการแปลภาษา (หรือรวบรวม) มันเป็น

len(str(100))

โดยเฉพาะอย่างยิ่งเนื่องจากเป็นวิธีเดียว (ฉันรู้) สำหรับการทำงาน ภาษารู้ว่าข้อผิดพลาดคืออะไรทำไมไม่แก้ไขมัน?

สำหรับตัวอย่างนี้ฉันใช้ Python แต่ฉันรู้สึกว่าบางสิ่งเล็ก ๆ นี้มันเป็นสากล


2
perl -e 'print length(100);'ภาพที่ 3

2
และลักษณะของภาษาและระบบประเภทของมัน นั่นเป็นส่วนหนึ่งของการออกแบบของหลาม

2
มันไม่สามารถแก้ไขได้เพราะมันไม่รู้จักปัญหาของคุณ บางทีคุณอาจต้องการทำสิ่งที่แตกต่างอย่างสิ้นเชิง เช่นการฟ้องร้องลูป แต่ไม่เคยทำอะไรเหมือนการเขียนโปรแกรมมาก่อน ดังนั้นหากแก้ไขได้ด้วยตนเองผู้ใช้จะไม่ทราบว่าเขาผิดหรือการดำเนินการจะไม่ทำตามที่เขาคาดไว้
Zaibis

5
@PieCrust Python ควรแปลงอย่างไร มันเป็นไม่ได้ความจริงที่ว่าทุกแปลงไปได้ที่จะกลับมาผลเดียวกัน
Bakuriu

7
@PieCrust: สตริงและอาร์เรย์เป็น iterables ทำไมจะstrเป็นวิธีโดยนัยในการแปลง int ให้เป็น iterable? แล้วไงrangeล่ะ หรือbin( hex, oct) หรือchr(หรือunichr)? ทั้งหมดเหล่านั้นกลับ iterables แม้ว่าstrดูเหมือนจะชัดเจนที่สุดสำหรับคุณในสถานการณ์นี้
njzk2

คำตอบ:


37

สำหรับสิ่งที่มันคุ้มค่าlen(str(100)), len(chr(100))และlen(hex(100))มีความแตกต่างกันทั้งหมด strคือไม่ได้วิธีเดียวที่จะทำให้การทำงานเนื่องจากมีมากกว่าหนึ่งแปลงที่แตกต่างกันในหลามจากจำนวนเต็มสตริง แน่นอนว่าหนึ่งในนั้นเป็นเรื่องธรรมดาที่สุด แต่ก็ไม่จำเป็นว่าจะไปโดยไม่บอกว่าเป็นสิ่งที่คุณต้องการ การแปลงโดยนัยหมายถึง "มันไปโดยไม่บอก"

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

นี่คือเหตุผลที่ (ส่วนใหญ่แล้ว) ไพ ธ อนชอบที่จะบอกเป็นนัย แต่ไม่ชอบที่จะเสี่ยง กรณีหลักที่ Python ทำการข่มขู่ประเภทนั้นเป็นแบบเลขคณิต จะช่วยให้1 + 1.0เพราะทางเลือกที่จะเป็นที่น่ารำคาญเกินไปที่จะอยู่ด้วย แต่ก็ไม่ได้ช่วยให้1 + "1"เพราะมันคิดว่าคุณควรจะต้องระบุว่าคุณหมายถึงint("1"), float("1"), ord("1"), str(1) + "1"หรือสิ่งอื่น นอกจากนี้ยังไม่อนุญาตให้(1,2,3) + [4,5,6]แม้ว่าจะสามารถ1 + 1.0กำหนดกฎระเบียบในการเลือกประเภทผลเช่นเดียวกับที่จะกำหนดกฎระเบียบในการเลือกประเภทของผล

ภาษาอื่นไม่เห็นด้วยและมีการแปลงโดยนัยจำนวนมาก ยิ่งพวกเขามีมากขึ้นเท่าไหร่พวกเขาก็ยิ่งมีความชัดเจนมากขึ้นเท่านั้น ลองจดจำกฎจากมาตรฐาน C สำหรับ "การส่งเสริมการขายจำนวนเต็ม" และ "การแปลงเลขคณิตปกติ" ก่อนอาหารเช้า!


+1 สำหรับการสาธิตวิธีการสันนิษฐานเริ่มต้นที่lenสามารถทำงานกับประเภทเดียวได้อย่างสมบูรณ์มีข้อบกพร่องพื้นฐาน
KChaloux

2
@KChaloux: จริงในตัวอย่างของฉันstr, chrและhexทำผลตอบแทนทุกประเภทเดียวกัน! ฉันพยายามนึกถึงประเภทที่แตกต่างกันซึ่งคอนสตรัคเตอร์สามารถใช้งานได้ แต่ฉันยังไม่ได้คิดอะไรเลย อุดมคติจะเป็นคอนเทนเนอร์Xที่len(X(100)) == 100;-) numpy.zerosดูเหมือนจะคลุมเครือเล็กน้อย
Steve Jessop

2
สำหรับตัวอย่างของปัญหาที่เป็นไปได้โปรดดูที่: docs.google.com/document/d/?hl=thและdestroyallsoftware.com/talks/wat
Jens Schauder

1
แปลงโดยปริยาย (ฉันคิดว่านี้เรียกว่าการบังคับ) สามารถก่อให้เกิดสิ่งที่น่ารังเกียจเหมือนมีa == b, b == cแต่a == cไม่เป็นความจริง
bgusach

คำตอบที่ยอดเยี่ยม ทุกสิ่งที่ฉันอยากจะพูดเพียงพูดดีกว่า! ข้อโต้แย้งเล็ก ๆ น้อย ๆ อย่างเดียวของฉันคือโปรโมชั่นจำนวนเต็ม C ค่อนข้างง่ายเมื่อเทียบกับการจำกฎการบังคับจาวาสคริปต์หรือล้อมรอบฐานรหัส C ++ ด้วยการใช้ตัวสร้างโดยปริยาย
GrandOpener

28

ดังที่ฉันเข้าใจแล้วการแปลงโดยนัยอาจทำให้เกิดข้อผิดพลาด

คุณไม่มีคำ: การแปลงนัยสามารถก่อให้เกิดRuntimeข้อผิดพลาด

สำหรับกรณีง่าย ๆ อย่างที่คุณแสดงมันค่อนข้างชัดเจนว่าคุณหมายถึงอะไร แต่ภาษาไม่สามารถใช้งานได้ในบางกรณี พวกเขาต้องทำงานกับกฎ สำหรับสถานการณ์อื่น ๆ อีกมากมายมันไม่ชัดเจนว่าโปรแกรมเมอร์ทำข้อผิดพลาด (โดยใช้ประเภทที่ไม่ถูกต้อง) หรือถ้าโปรแกรมเมอร์ต้องการทำสิ่งที่รหัสถือว่าพวกเขาตั้งใจจะทำ

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

สิ่งหนึ่งที่ควรทราบคือการแปลงโดยนัยทำให้คอมไพเลอร์ซับซ้อนขึ้นเล็กน้อย คุณจะต้องระมัดระวังมากขึ้นเกี่ยวกับรอบ (ลองแปลงนี้จาก A ไป B; โอ๊ะที่ไม่ได้ทำงาน แต่มีการแปลงจาก B ไป A และจากนั้นคุณจำเป็นต้องกังวลเกี่ยวกับ C และ D ขนาดรอบเกินไป ) ซึ่ง เป็นแรงจูงใจเล็กน้อยเพื่อหลีกเลี่ยงการแปลงโดยนัย


ส่วนใหญ่พูดคุยเกี่ยวกับฟังก์ชั่นที่สามารถทำงานกับประเภทเดียวเท่านั้นทำให้การแปลงชัดเจน อะไรจะเป็นสิ่งที่ใช้ได้กับหลายประเภทและประเภทที่คุณใส่จะสร้างความแตกต่าง? print ("295") = print (295) ดังนั้นจะไม่สร้างความแตกต่างยกเว้นตัวแปร สิ่งที่คุณพูดมีเหตุผลยกเว้นย่อหน้า 3 มิติ ... คุณสามารถย้ำอีกครั้งได้ไหม
Quelklef

30
@PieCrust - 123 + "456" คุณต้องการ "123456" หรือ 579 หรือไม่ ภาษาการเขียนโปรแกรมไม่ได้ทำบริบทดังนั้นจึงเป็นเรื่องยากสำหรับพวกเขาที่จะ "คิดออก" เนื่องจากพวกเขาจะต้องรู้บริบทที่มีการเพิ่มเข้ามาย่อหน้าใดไม่ชัดเจน?
Telastyn

1
นอกจากนี้บางทีการตีความในฐานะฐาน 10 ไม่ใช่สิ่งที่คุณต้องการ ใช่การแปลงโดยนัยเป็นสิ่งที่ดีแต่เฉพาะในกรณีที่พวกเขาไม่สามารถซ่อนข้อผิดพลาดได้
Deduplicator

13
@PieCrust: บอกตามตรงฉันไม่เคยคาดหวังว่าlen(100)จะได้กลับมา3อีก ฉันจะพบว่ามันมีมากขึ้นใช้งานง่ายสำหรับมันในการคำนวณจำนวนของบิต (หรือ bytes) 100ในการเป็นตัวแทนของ
user541686

3
ฉันกับ @ Mehrdad จากตัวอย่างของคุณเป็นที่ชัดเจนว่าคุณคิดว่ามันชัดเจน 100% ที่len(100)ควรให้จำนวนตัวอักษรแทนทศนิยมของจำนวน 100 แต่จริง ๆ แล้วมันเป็นสมมติฐานที่คุณทำในขณะที่ไม่รู้ตัว ของพวกเขา. คุณสามารถทำให้ข้อโต้แย้งที่แข็งแกร่งทำไมจำนวนบิตหรือไบต์หรืออักขระเลขฐานสิบหกของการเป็นตัวแทนที่ ( 64-> 2 ตัวอักษร) len()ควรจะส่งกลับโดย
funkwurm

14

การแปลงโดยนัยนั้นค่อนข้างเป็นไปได้ที่จะทำ สถานการณ์ที่คุณมีปัญหาคือเมื่อคุณไม่รู้ว่าควรจะทำงานอย่างไร

ตัวอย่างนี้สามารถเห็นได้ใน Javascript ที่+ผู้ประกอบการทำงานในรูปแบบที่แตกต่างกันในเวลาที่ต่างกัน

>>> 4 + 3
7
>>> "4" + 3
43
>>> 4 + "3"
43

หากหนึ่งในอาร์กิวเมนต์เป็นสตริงตัว+ดำเนินการคือการต่อสายอักขระมิฉะนั้นจะเป็นการเพิ่ม

หากคุณได้รับการโต้แย้งและไม่ทราบว่ามันเป็นสตริงหรือจำนวนเต็มและต้องการเพิ่มเข้าไปด้วยมันอาจเป็นเรื่องยุ่งเล็กน้อย

อีกวิธีในการจัดการกับสิ่งนี้คือจากมรดกพื้นฐาน (ที่ perl ดังนี้ - ดูการเขียนโปรแกรมเป็นเรื่องยาก Let's Scripting ... )

ในขั้นพื้นฐานlenฟังก์ชั่นจะทำให้เกิดความรู้สึกถูกเรียกบน String เท่านั้น (เอกสารสำหรับvisual Basic : "นิพจน์สตริงหรือชื่อตัวแปรใด ๆ ที่ถูกต้องถ้า Expression เป็นประเภทวัตถุ Object ฟังก์ชั่น Len จะส่งกลับขนาดตามที่มันจะถูกเขียนลงในไฟล์ ฟังก์ชัน FilePut ")

Perl เป็นไปตามแนวคิดของบริบทนี้ ความสับสนที่มีอยู่ใน JavaScript กับการแปลงโดยนัยของชนิดสำหรับ+ผู้ประกอบการเป็นบางครั้งและบางครั้งนอกจากเรียงต่อกันไม่ได้เกิดขึ้นใน Perl เพราะ+เป็นเสมอนอกจากนี้และ.เป็นเสมอเรียงต่อกัน

หากมีการใช้บางสิ่งในบริบทสเกลาร์มันเป็นสเกลาร์ (เช่นใช้รายการเป็นสเกลาร์รายการจะทำงานเหมือนเป็นตัวเลขที่สอดคล้องกับความยาว) หากคุณใช้ตัวดำเนินการสตริง ( eqสำหรับการทดสอบความเท่าเทียมกันcmpสำหรับการเปรียบเทียบสตริง) สเกลาร์ถูกใช้ราวกับว่ามันเป็นสตริง ในทำนองเดียวกันหากมีการใช้บางสิ่งในบริบททางคณิตศาสตร์ ( ==สำหรับการทดสอบความเท่าเทียมกันและ<=>การเปรียบเทียบเชิงตัวเลข) สเกลาร์จะถูกใช้ราวกับว่าเป็นตัวเลข

กฎพื้นฐานสำหรับการเขียนโปรแกรมทั้งหมดคือ "ทำในสิ่งที่ทำให้คนประหลาดใจน้อยที่สุด" นี่ไม่ได้หมายความว่าไม่มีความประหลาดใจอยู่ในนั้น แต่ความพยายามคือการทำให้คน ๆ นั้นประหลาดใจน้อยที่สุด

เมื่อไปถึงลูกพี่ลูกน้องอย่างใกล้ชิดของ perl - php มีสถานการณ์ที่ผู้ปฏิบัติงานสามารถทำอะไรบางอย่างในบริบทสตริงหรือตัวเลขและพฤติกรรมสามารถสร้างความประหลาดใจให้กับผู้คน ++ประกอบเป็นตัวอย่างหนึ่งเช่น ในตัวเลขมันทำงานตรงตามที่คาดไว้ เมื่อดำเนินการกับสตริงเช่น"aa"จะเพิ่มสตริง ( $foo = "aa"; $foo++; echo $foo;พิมพ์ab) นอกจากนี้ยังจะเกลือกกลิ้งเพื่อที่ว่าเมื่อเพิ่มขึ้นจะกลายเป็นaz baสิ่งนี้ไม่น่าประหลาดใจโดยเฉพาะอย่างยิ่ง

$foo = "3d8";
echo "$foo\n";
$foo++;
echo "$foo\n";
$foo++;
echo "$foo\n";
$foo++;
echo "$foo\n";

( ideone )

สิ่งนี้พิมพ์ออกมา:

3d8
3d9
3e0
4

ยินดีต้อนรับสู่อันตรายของการแปลงและตัวดำเนินการโดยปริยายซึ่งทำหน้าที่แตกต่างกันในสายอักขระเดียวกัน (Perl จัดการโค้ดบล็อกนั้นแตกต่างกันเล็กน้อย - ตัดสินใจว่า"3d8"เมื่อตัว++ดำเนินการถูกนำไปใช้เป็นค่าตัวเลขตั้งแต่เริ่มต้นและไป4ทันที ( ideone ) - พฤติกรรมนี้อธิบายได้ดีในperlop: การเพิ่มขึ้นอัตโนมัติและการลดลงอัตโนมัติ )

ทีนี้ทำไมภาษาหนึ่งถึงทำสิ่งหนึ่งทางหนึ่งและอีกภาษาหนึ่งทำให้อีกความคิดการออกแบบของนักออกแบบ ปรัชญาของ Perl คือมีมากกว่าหนึ่งวิธีที่จะทำ - และฉันสามารถคิดถึงวิธีการบางอย่างในการดำเนินการบางอย่าง ในอีกทางหนึ่ง Python มีปรัชญาที่อธิบายไว้ในPEP 20 - The Zen of Pythonซึ่งกล่าวถึง (เหนือสิ่งอื่นใด): "ควรมีอย่างใดอย่างหนึ่ง - และดีกว่าเพียงวิธีเดียวเท่านั้น - ชัดเจนวิธีที่จะทำ"

ความแตกต่างของการออกแบบเหล่านี้นำไปสู่ภาษาที่แตกต่างกัน มีวิธีหนึ่งในการรับความยาวของตัวเลขใน Python การแปลงโดยปริยายนั้นขัดกับปรัชญานี้

การอ่านที่เกี่ยวข้อง: ทำไม Ruby จึงไม่มีการแปลง Fixnum ให้เป็น String โดยนัย?


IMHO ภาษา / กรอบการทำงานที่ดีมักจะมีหลายวิธีในการทำสิ่งต่าง ๆ ที่จัดการกับมุมกรณีทั่วไปแตกต่างกัน (ดีกว่าที่จะจัดการกับกรณีมุมทั่วไปครั้งเดียวในภาษาหรือกรอบกว่า 1,000 ครั้งใน 1,000 โปรแกรม); ความจริงที่ว่าผู้ให้บริการสองรายทำสิ่งเดียวกันเวลาส่วนใหญ่ไม่ควรพิจารณาว่าเป็นสิ่งที่ไม่ดีถ้าเมื่อพฤติกรรมของพวกเขาแตกต่างกันจะมีประโยชน์ต่อการเปลี่ยนแปลงแต่ละอย่าง ไม่ควรยากที่จะเปรียบเทียบตัวแปรตัวเลขสองตัวxและyในลักษณะที่จะให้ความสัมพันธ์หรือการจัดอันดับที่เท่าเทียมกัน แต่ตัวดำเนินการเปรียบเทียบ IIRC Python ของ ...
supercat

... ใช้ความสัมพันธ์ที่ไม่เท่าเทียมกันหรือการจัดอันดับและ Python ไม่ได้ให้บริการที่สะดวกสบายใด ๆ
supercat

12

ColdFusion ทำสิ่งนี้เป็นส่วนใหญ่ มันกำหนดชุดของกฎเพื่อจัดการกับการแปลงโดยนัยของคุณมีประเภทตัวแปรเดียวและไปที่นั่น

ผลลัพธ์คืออนาธิปไตยทั้งหมดโดยที่การเพิ่ม "4a" ถึง 6 คือ 6.16667

ทำไม? ทีนี้, เพราะตัวแปรแรกของสองตัวนั้นคือตัวเลข, ผลลัพธ์จะเป็นตัวเลข "4a" แยกเป็นวันที่และถูกมองว่าเป็น "4 AM" 4.00 น. คือ 4:00 น. / 24:00 น. หรือ 1 ใน 6 ของวัน (0.16667) เพิ่มเป็น 6 และคุณจะได้รับ 6.16667

รายการมีอักขระคั่นเริ่มต้นของเครื่องหมายจุลภาคดังนั้นหากคุณเพิ่มรายการลงในรายการที่มีเครื่องหมายจุลภาคคุณก็เพิ่มสองรายการ นอกจากนี้รายการเป็นสตริงลับๆเพื่อให้สามารถแยกวิเคราะห์เป็นวันที่หากมีเพียง 1 รายการ

การเปรียบเทียบสตริงจะตรวจสอบว่าสตริงทั้งสองสามารถแยกวิเคราะห์เป็นวันที่ก่อนได้หรือไม่ เนื่องจากไม่มีประเภทวันที่จึงเป็นเช่นนั้น สิ่งเดียวกันสำหรับตัวเลขและสตริงที่มีตัวเลขสัญกรณ์ฐานแปดและบูลีน ("จริง" และ "ใช่" ฯลฯ )

แทนที่จะล้มเหลวอย่างรวดเร็วและรายงานข้อผิดพลาดแทน ColdFusion จะจัดการการแปลงประเภทข้อมูลสำหรับคุณ และไม่ใช่วิธีที่ดี

แน่นอนคุณสามารถแก้ไขการแปลงโดยนัยได้ด้วยการเรียกฟังก์ชันที่ชัดเจนเช่น DateCompare ... แต่คุณสูญเสีย "ประโยชน์" ของการแปลงโดยนัยแล้ว


สำหรับ ColdFusion นี่เป็นวิธีที่จะช่วยให้นักพัฒนามีอำนาจมากขึ้น โดยเฉพาะอย่างยิ่งเมื่อนักพัฒนาเหล่านั้นคุ้นเคยกับ HTML (ColdFusion ทำงานร่วมกับแท็กมันเรียกว่า CFML หลังจากนั้นพวกเขาก็เพิ่มการเขียนสคริปต์ผ่าน<cfscript>เช่นกันซึ่งคุณไม่จำเป็นต้องเพิ่มแท็กสำหรับทุกสิ่ง) และใช้งานได้ดีเมื่อคุณต้องการให้บางอย่างทำงาน แต่เมื่อคุณต้องการสิ่งต่าง ๆ ที่จะเกิดขึ้นอย่างแม่นยำยิ่งขึ้นคุณต้องมีภาษาที่ปฏิเสธที่จะทำ Conversion แบบไม่แน่นอนสำหรับสิ่งที่ดูเหมือนว่าอาจเป็นความผิดพลาด


1
ว้าว "อนาธิปไตยทั้งหมด" แน่นอน!
hoosierEE

7

คุณกำลังจะบอกว่าการแปลงนัยอาจจะเป็นความคิดที่ดีสำหรับการดำเนินงานที่มีความชัดเจนเช่นint a = 100; len(a)ที่คุณเห็นได้ชัดว่าหมายถึงการแปลง int เพื่อสตริงก่อนที่จะเรียก

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

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

ตรวจสอบความเศร้าโศกของ Javascript ด้วยการแปลงโดยนัยทั้งหมดที่ดำเนินการโดย == ดังนั้นมากตอนนี้ที่หลายคนแนะนำให้ติดกับตัวดำเนินการ no-implicit-conversion ===


6

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

def approx_log_10(s):
    return len(s)
print approx_log_10(3.5)  # "3" is probably not what I'm expecting here...

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

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


3

การแปลงโดยนัยอาจเป็นความเจ็บปวดที่แท้จริงในการทำงานกับ ใน PowerShell:

$a = $(dir *.xml) # typeof a is a list, because there are two XML files in the folder.
$a = $(dir *.xml) # typeof a is a string, because there is one XML file in the folder.

ทันใดนั้นก็จำเป็นต้องมีการทดสอบเพิ่มขึ้นสองเท่าและมีข้อผิดพลาดเพิ่มขึ้นเป็นสองเท่า


2

การปลดเปลื้องอย่างชัดเจนมีความสำคัญสำหรับพวกเขากำลังทำให้เจตนาของคุณชัดเจน ก่อนอื่นให้ใช้การปลดเปลื้องที่ชัดเจนจะบอกเล่าเรื่องราวแก่คนที่กำลังอ่านโค้ดของคุณ พวกเขาเปิดเผยว่าคุณตั้งใจทำสิ่งที่คุณทำ ยิ่งไปกว่านั้นคอมไพเลอร์ก็เช่นเดียวกัน ตัวอย่างต่อไปนี้ผิดกฎหมายใน C #

double d = 3.1415926;
// code elided
int i = d;

นักแสดงจะทำให้คุณคลายความแม่นยำซึ่งอาจเป็นจุดบกพร่องได้ง่าย ดังนั้นคอมไพเลอร์ปฏิเสธที่จะรวบรวม เมื่อใช้นักแสดงอย่างชัดเจนคุณกำลังบอกคอมไพเลอร์ว่า "เฮ้ฉันรู้ว่าฉันกำลังทำอะไรอยู่" และเขาจะไป: "โอเค!" และรวบรวม


1
ที่จริงแล้วฉันไม่ชอบการปลดเปลื้องที่ชัดเจนที่สุดมากกว่าการบอกเป็นนัย ๆ IMHO สิ่งเดียวที่(X)yควรหมายถึงคือ "ฉันคิดว่า Y สามารถแปลงเป็น X ได้ให้ทำการแปลงถ้าเป็นไปได้หรือโยนข้อยกเว้นถ้าไม่ใช่"; ถ้าประสบความสำเร็จแปลงหนึ่งควรจะสามารถที่จะคาดการณ์สิ่งที่มีค่าที่เกิดขึ้นจะเป็น * โดยไม่ต้องรู้กฎพิเศษใด ๆ เกี่ยวกับการแปลงจากชนิดของประเภทy Xหากขอให้แปลง -1.5 และ 1.5 เป็นจำนวนเต็มบางภาษาจะให้ผล (-2,1) บางส่วน (-2,2) บางส่วน (-1,1) และบางส่วน (-1,2) ในขณะที่กฎของ C แทบจะไม่ปิดบัง ...
SuperCat

1
... การแปลงแบบนั้นดูเหมือนว่ามันจะถูกดำเนินการอย่างเหมาะสมมากกว่าวิธีการผ่านทาง cast (เลว. NET ไม่ได้รวมฟังก์ชั่นรอบและแปลงที่มีประสิทธิภาพและของ Java ถูกมากเกินไปในแบบโง่)
supercat

คุณกำลังบอกคอมไพเลอร์ว่า " ฉันคิดว่าฉันรู้ว่าฉันทำอะไรอยู่"
gnasher729

@ gnasher729 มีความจริงบางอย่างในนั้น :)
Paul Kertscher

1

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

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

เมื่อวันก่อนเพื่อนของฉันคนหนึ่งถามอายุ 2 ขวบของเขาว่า 20 +20 คืออะไรและเขาตอบในปี 2020 ฉันบอกเพื่อนของฉันว่า "เขากำลังจะเป็นโปรแกรมเมอร์จาวาสคริปต์"

ใน Javascript:

20+20
40

20+"20"
"2020"

ดังนั้นคุณสามารถเห็นปัญหาที่ปลดเปลื้องโดยนัยสามารถสร้างและทำไมมันไม่ใช่สิ่งที่สามารถแก้ไขได้ การแก้ไขที่ฉันจะโต้แย้งคือการใช้ปลดเปลื้องชัดเจน

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