เหตุใดภาษาหลักส่วนใหญ่จึงไม่สนับสนุนไวยากรณ์“ x <y <z” สำหรับการเปรียบเทียบแบบบูลีน 3 ทาง


34

หากฉันต้องการเปรียบเทียบตัวเลขสองตัว (หรือเอนทิตีที่มีการจัดลำดับที่ดีอื่น ๆ ) ฉันจะทำเช่นx < yนั้น ถ้าผมต้องการเปรียบเทียบสามของพวกเขา, x < y < zนักเรียนพีชคณิตโรงเรียนมัธยมจะแนะนำพยายาม โปรแกรมเมอร์ในตัวฉันจะตอบกลับด้วย "ไม่นั่นไม่ถูกต้องคุณต้องทำx < y && y < z"

ภาษาส่วนใหญ่ที่ฉันพบเจอดูเหมือนจะไม่สนับสนุนไวยากรณ์นี้ซึ่งเป็นเรื่องแปลกเพราะมันเป็นเรื่องธรรมดาในวิชาคณิตศาสตร์ Python เป็นข้อยกเว้นที่น่าสังเกต JavaScript ดูเหมือนข้อยกเว้น แต่จริงๆแล้วเป็นเพียงผลพลอยได้ที่โชคร้ายของลำดับความสำคัญของผู้ปฏิบัติงานและการแปลงโดยนัย ใน Node.js, 1 < 3 < 2ประเมินเพราะมันจริงๆtrue(1 < 3) < 2 === true < 2 === 1 < 2

ดังนั้นคำถามของฉันคือ: เหตุใดจึงx < y < zไม่มีอยู่ทั่วไปในภาษาการเขียนโปรแกรมด้วยความหมายที่คาดหวัง


1
นี่คือไฟล์ไวยากรณ์ซึ่งพวกเขาคล่องแคล่วติดที่ถูกต้องในเอกสารหลาม - ฉันไม่คิดว่ามันเป็นเรื่องยากที่: docs.python.org/reference/grammar.html
แอรอนฮอลล์

ฉันไม่รู้ภาษาอื่น ๆ รวมทั้งรู้จัก Python แต่ฉันสามารถพูดกับความเรียบง่ายของการตีความของ Python ได้ บางทีฉันควรตอบ แต่ฉันไม่เห็นด้วยกับข้อสรุปของ gnasher729 เกี่ยวกับการทำความเสียหาย
Aaron Hall

@ErikEidt - ความต้องการสามารถเขียนสำนวนทางคณิตศาสตร์ในแบบที่เราสอนในโรงเรียนมัธยม (หรือก่อนหน้า) ทุกคนที่มีความโน้มเอียงทางคณิตศาสตร์รู้ว่า $ a <b <c <d $ หมายถึงอะไร เพียงเพราะคุณสมบัติที่มีอยู่ไม่ได้หมายความว่าคุณต้องใช้มัน ผู้ที่ไม่ชอบสามารถสร้างกฎส่วนบุคคลหรือโครงการห้ามการใช้งาน
David Hammen

2
ฉันคิดว่าสิ่งที่เกิดขึ้นคือมันจะดีกว่าสำหรับทีม C # (เป็นตัวอย่าง) เพื่อสำรวจ LINQ และในอนาคตอาจมีการบันทึกประเภทและรูปแบบการจับคู่มากกว่าที่จะเพิ่มน้ำตาล syntactic ที่จะช่วยให้ผู้คนประหยัด 4 การกดแป้นพิมพ์ เพิ่มการแสดงออกใด ๆ (คุณยังสามารถเขียน helpermethods เหมือนstatic bool IsInRange<T>(this T candidate, T lower, T upper) where T : IComparable<T>ว่ามันจริงๆรบกวนจิตใจคุณเห็น&&s)
sara

1
SQL ค่อนข้าง "กระแสหลัก" และคุณสามารถเขียน "x ระหว่าง 1 ถึง 10"
JoelFan

คำตอบ:


30

สิ่งเหล่านี้เป็นตัวดำเนินการแบบไบนารีซึ่งเมื่อถูกล่ามโซ่โดยปกติและเป็นธรรมชาติจะสร้างต้นไม้ที่เป็นนามธรรมเช่น:

ต้นไม้ไวยากรณ์นามธรรมปกติสำหรับผู้ประกอบการแบบไบนารี

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

ทรีไวยากรณ์ของเคสพิเศษ

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


1
"แล้วคุณจะได้รับข้อผิดพลาดประเภทพยายามทำบูลีน <z" - ไม่ใช่ว่าคอมไพเลอร์อนุญาตให้มีการผูกมัดโดยการประเมิน y แบบแทนที่สำหรับการเปรียบเทียบซี "นั่นเป็นการเพิ่มพื้นที่จำนวนมากสำหรับสิ่งที่ผิดพลาดที่นักออกแบบภาษาจะหลีกเลี่ยงหากเป็นไปได้" ที่จริงแล้ว Python ไม่มีปัญหาในการทำเช่นนี้และตรรกะสำหรับการแยกวิเคราะห์จะถูก จำกัด อยู่ที่ฟังก์ชันเดียว: hg.python.org/cpython/file/tip/Python/ast.c#l1122 - ไม่มากสำหรับสิ่งที่ต้องไป ไม่ถูกต้อง. "บางครั้งทำหน้าที่เหมือนโอเปอเรเตอร์ไบนารีและบางครั้งก็ทำหน้าที่เหมือนโอเปอเรเตอร์ trinary" ใน Python โซ่เปรียบเทียบทั้งหมดนั้นประกอบไปด้วยสามส่วน
Aaron Hall

2
ฉันไม่เคยบอกว่ามันไม่สามารถทำได้เพียงแค่ทำงานพิเศษที่มีความซับซ้อนเป็นพิเศษ ภาษาอื่น ๆ ที่ไม่ได้มีการเขียนใด ๆรหัสแยกต่างหากสำหรับการจัดการดำเนินการเปรียบเทียบของพวกเขา คุณได้รับมันฟรีกับตัวดำเนินการไบนารีอื่น ๆ คุณเพียงแค่ต้องระบุความสำคัญของพวกเขา
Karl Bielefeldt

ใช่ แต่ ... มีเป็นแล้วผู้ประกอบการ Ternaryสามารถใช้ได้ในหลายภาษาหรือไม่?
JensG

1
@JensG การ denotation ของ ternary หมายความว่าใช้เวลา 3 ข้อโต้แย้ง ในบริบทของลิงก์ของคุณเป็นตัวดำเนินการเงื่อนไขที่ประกอบไปด้วยสามส่วน เห็นได้ชัดว่า "trinary" ในคำประกาศเกียรติคุณสำหรับผู้ประกอบการที่ดูเหมือนจะใช้เวลา 2 แต่ใช้เวลา 3 จริงปัญหาหลักของฉันด้วยคำตอบนี้เป็นส่วนใหญ่ FUD
Aaron Hall

2
ฉันเป็นหนึ่งใน downvoters ของคำตอบที่ยอมรับนี้ (@JesseTG: โปรดยอมรับคำตอบนี้) คำถามนี้ทำให้เกิดความสับสนในความx<y<zหมายหรือที่สำคัญกว่าx<y<=zนั้น คำตอบนี้ตีความx<y<zว่าเป็นผู้ประกอบการ trinary นั่นคือวิธีที่นิพจน์ทางคณิตศาสตร์ที่นิยามไว้อย่างดีนี้ไม่ควรตีความ แทนที่จะจดชวเลขx<y<z (x<y)&&(y<z)การเปรียบเทียบแต่ละรายการยังคงเป็นแบบไบนารี่
David Hammen

37

เหตุใดจึงx < y < zไม่มีอยู่ทั่วไปในภาษาการเขียนโปรแกรม

ในคำตอบนี้ฉันสรุปได้ว่า

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

บทนำ

ฉันสามารถพูดได้จากมุมมองของ Pythonist กับคำถามนี้ ฉันเป็นผู้ใช้ภาษาที่มีคุณสมบัตินี้และฉันชอบศึกษารายละเอียดการใช้ภาษา นอกเหนือจากนี้ฉันค่อนข้างคุ้นเคยกับกระบวนการเปลี่ยนภาษาเช่น C และ C ++ (มาตรฐาน ISO อยู่ภายใต้การควบคุมของคณะกรรมการและเวอร์ชันปี) และฉันได้ดูทั้ง Ruby และ Python ใช้การเปลี่ยนแปลงที่ทำลาย

เอกสารและการใช้งานของไพ ธ อน

จากเอกสาร / ไวยากรณ์เราเห็นว่าเราสามารถเชื่อมโยงนิพจน์จำนวนเท่าใดก็ได้กับตัวดำเนินการเปรียบเทียบ:

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

และเอกสารประกอบระบุเพิ่มเติม:

การเปรียบเทียบสามารถถูกล่ามโซ่โดยพลการตัวอย่างเช่น x <y <= z เทียบเท่ากับ x <y และ y <= z ยกเว้นว่า y ถูกประเมินเพียงครั้งเดียว (แต่ในทั้งสองกรณี z ไม่ได้รับการประเมินเลยเมื่อพบ x <y เป็นเท็จ)

สมการเชิงตรรกะ

ดังนั้น

result = (x < y <= z)

เป็นเหตุผลเทียบเท่าในแง่ของการประเมินผลของx, yและzมีข้อยกเว้นที่yได้รับการประเมินครั้งที่สอง:

x_lessthan_y = (x < y)
if x_lessthan_y:       # z is evaluated contingent on x < y being True
    y_lessthan_z = (y <= z)
    result = y_lessthan_z
else:
    result = x_lessthan_y

(x < y <= z)อีกครั้งที่แตกต่างคือปีได้รับการประเมินเพียงครั้งเดียวด้วย

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

การตรวจสอบทรีไวยากรณ์แยกวิเคราะห์

เราสามารถตรวจสอบว่า Python แยกวิเคราะห์ตัวดำเนินการเปรียบเทียบที่ถูกโยงโซ่:

>>> import ast
>>> node_obj = ast.parse('"foo" < "bar" <= "baz"')
>>> ast.dump(node_obj)
"Module(body=[Expr(value=Compare(left=Str(s='foo'), ops=[Lt(), LtE()],
 comparators=[Str(s='bar'), Str(s='baz')]))])"

ดังนั้นเราจะเห็นได้ว่านี่ไม่ใช่เรื่องยากที่ Python หรือภาษาอื่นจะแยกวิเคราะห์

>>> ast.dump(node_obj, annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE()], [Str('bar'), Str('baz')]))])"
>>> ast.dump(ast.parse("'foo' < 'bar' <= 'baz' >= 'quux'"), annotate_fields=False)
"Module([Expr(Compare(Str('foo'), [Lt(), LtE(), GtE()], [Str('bar'), Str('baz'), Str('quux')]))])"

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

บทสรุปเกี่ยวกับ Python

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

โปรดทราบว่ามีการอ่านรหัสมากกว่าที่เขียนไว้ การเปลี่ยนแปลงที่ปรับปรุงการอ่านรหัสที่ควรได้รับการกอดไม่ลดโดยการเพิ่มภูตผีทั่วไปของความกลัวความไม่แน่นอนและไม่ต้องสงสัยเลย

แล้วเหตุใด x <y <z จึงไม่มีอยู่ทั่วไปในภาษาการเขียนโปรแกรม

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

คำถามที่คล้ายกันสามารถถามเกี่ยวกับคุณสมบัติภาษาที่สำคัญอื่น ๆ

เหตุใดจึงไม่มีการสืบทอดหลายรายการใน Java หรือ C # ไม่มีคำตอบที่ดีสำหรับคำถามนี้ บางทีนักพัฒนาอาจขี้เกียจเกินไปอย่างที่บ็อบมาร์ตินอ้างเหตุผลและเหตุผลก็เป็นข้อแก้ตัว และการสืบทอดหลายครั้งเป็นหัวข้อที่ยิ่งใหญ่ในสาขาวิทยาศาสตร์คอมพิวเตอร์ มีความสำคัญมากกว่าการผูกมัดผู้ปฏิบัติงานอย่างแน่นอน

มีวิธีแก้ไขปัญหาง่าย ๆ อยู่

การโยงผู้ประกอบการเปรียบเทียบนั้นสง่างาม แต่ก็ไม่สำคัญเท่ากับมรดกหลายอย่าง และเช่นเดียวกับ Java และ C # มีอินเทอร์เฟซเป็นวิธีแก้ปัญหาดังนั้นทุกภาษาสำหรับการเปรียบเทียบหลาย ๆ ครั้ง - คุณเพียงเชื่อมโยงการเปรียบเทียบกับบูลีน "และ" s ซึ่งทำงานได้ง่ายพอ

ภาษาส่วนใหญ่ควบคุมโดยคณะกรรมการ

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

ภาษาที่ไม่มีคุณสมบัตินี้สามารถเปลี่ยนแปลงได้หรือไม่?

หากภาษายอมให้x < y < zไม่มีความหมายทางคณิตศาสตร์ที่คาดหวังนี่จะเป็นการเปลี่ยนแปลงที่ไม่คาดคิด หากไม่อนุญาตให้ใช้ในตอนแรกมันจะเพิ่มขึ้นเล็กน้อย

ทำลายการเปลี่ยนแปลง

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


สุจริตผมใช้ไม่มีปัญหากับความหมายที่มีให้โดยภาษาที่การดำเนินงานเปรียบเทียบห่วงโซ่เช่น `x <Y <Z` แต่มันเป็นเรื่องเล็ก ๆ น้อย ๆ สำหรับนักพัฒนาจิตใจแผนที่จะx < y < z (x < y) && (y < z)การเลือก nits แบบจำลองทางจิตสำหรับการเปรียบเทียบที่ถูกล่ามโซ่คือคณิตศาสตร์ทั่วไป การเปรียบเทียบแบบคลาสสิคไม่ใช่คณิตศาสตร์โดยทั่วไป แต่เป็นตรรกะบูลีน ก่อให้เกิดคำตอบไบนารีx < y ก่อให้เกิดคำตอบไบนารี สร้างคำตอบที่อธิบาย ตรรกะประกอบด้วยไม่ถูกผูกมัดอย่างไร้เดียงสา {0}y < z{1}{0} && {1}
K. Alan Bates

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

2
เหตุผลสำคัญที่มีเพียงไม่กี่ภาษาที่ใช้คุณลักษณะนี้คือก่อนหน้ากุยโดไม่มีใครแม้แต่จะคิดถึงมัน ภาษาที่สืบทอดมาจาก C ไม่สามารถรับ "ถูกต้อง" (ถูกต้องทางคณิตศาสตร์) ในตอนนี้เพราะนักพัฒนาของ C ทำให้มัน "ผิด" (ผิดทางคณิตศาสตร์) มานานกว่า 40 ปีที่ผ่านมา มีจำนวนมากออกมีรหัสที่ขึ้นอยู่กับธรรมชาติของวิธี counterintuitive x<y<zภาษาที่แปลความหมายเป็น ภาษามีโอกาสครั้งหนึ่งที่จะได้รับสิ่งนี้ถูกต้องและโอกาสหนึ่งคือเมื่อเริ่มต้นภาษา
David Hammen

1
@ K.AlanBates คุณทำ 2 คะแนน: 1) การผูกมัดผู้ดำเนินการเป็นเรื่องเหลวไหลและ 2) น้ำตาล syntactic นั้นไม่มีค่า ถึงครั้งแรก: ฉันได้แสดงให้เห็นว่าการผูกมัดผู้ประกอบการเป็นกำหนด 100% ใช่หรือไม่? บางทีโปรแกรมเมอร์บางคนขี้เกียจเกินไปที่จะขยายความสามารถในการเข้าใจโครงสร้าง? จนถึงจุดที่สอง: ฟังดูเหมือนว่าคุณโต้เถียงกับการอ่านโดยตรงหรือไม่? น้ำตาลซินแทคติคโดยทั่วไปถือว่าไม่ดีเมื่อปรับปรุงการอ่านหรือไม่ ถ้าเป็นเรื่องปกติที่จะต้องคิดแบบนี้ทำไมโปรแกรมเมอร์ไม่ต้องการที่จะสื่อสารอย่างนี้? ควรเขียนโค้ดเพื่ออ่านใช่ไหม
Aaron Hall

2
I have watched both Ruby and Python implement breaking changes.สำหรับผู้ที่มีความอยากรู้อยากเห็นว่านี่คือการเปลี่ยนแปลงทำลายใน C # 5.0 ตัวแปรที่เกี่ยวข้องกับห่วงและฝาปิด: blogs.msdn.microsoft.com/ericlippert/2009/11/12/...
user2023861

13

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

คุณอาจขอผู้ประกอบการที่สาม ตัวอย่างจะเป็น x <y <z ตอนนี้เราอนุญาตให้มีการรวมกันของผู้ประกอบการ? เห็นได้ชัดว่า x> y> z หรือ x> = y> = z หรือ x> y> = z หรืออาจ x == y == z ควรได้รับอนุญาต แล้ว x <y> z x! = y! = z? อันสุดท้ายหมายความว่าอะไร, x! = y และ y! = z หรือว่าทั้งสามแตกต่างกัน?

การส่งเสริมการโต้แย้งในขณะนี้ใน C หรือ C ++ การโต้แย้งจะได้รับการเลื่อนระดับเป็นประเภททั่วไป ดังนั้น x <y <z ค่าเฉลี่ยของ x จึงเป็นสองเท่า แต่ y และ z นั้นมีความยาว int? ทั้งสามได้รับการเลื่อนตำแหน่งเป็นสองเท่า? หรือว่า y ถูกจับเป็นสองเท่าหนึ่งครั้งและนาน int อีกครั้ง? จะเกิดอะไรขึ้นถ้าใน C ++ หนึ่งหรือทั้งสองตัวดำเนินการมากเกินไป?

และสุดท้ายคุณอนุญาตให้ตัวถูกดำเนินการจำนวนเท่าใด? ชอบ <b> c <d> e <f> g หรือไม่

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


4
ดังนั้นในระยะสั้นมันเป็นเพียงคุณสมบัติที่ยากในการออกแบบที่ดี
Jon Purdy

2
นี่ไม่ใช่เหตุผลที่จะอธิบายว่าทำไมไม่มีภาษาที่รู้จักกันดีมีคุณสมบัตินี้ ตามความเป็นจริงมันค่อนข้างง่ายที่จะรวมไว้ในภาษาในวิธีที่กำหนดไว้อย่างดี มันเป็นเพียงเรื่องของการดูมันเป็นรายการที่เชื่อมต่อโดยผู้ประกอบการประเภทที่คล้ายกันแทนผู้ประกอบการทุกคนเป็นไบนารีหนึ่ง เดียวกันสามารถทำได้สำหรับผลรวมx + y + zมีความแตกต่างเพียงอย่างเดียวที่ไม่ได้บ่งบอกถึงความแตกต่างทางความหมายใด ๆ ดังนั้นมันจึงไม่มีภาษาที่เป็นที่รู้จักกันดี
cmaster

1
ฉันคิดว่าใน Python มันเป็นการเพิ่มประสิทธิภาพเล็กน้อย ( x < y < zเทียบเท่ากับ((x < y) and (y < z))แต่มีการyประเมินเพียงครั้งเดียว ) ซึ่งฉันคิดว่าภาษาที่คอมไพล์แล้วจะปรับวิธีการของพวกเขาให้เหมาะสม "เนื่องจากประโยชน์ของมันมีขนาดเล็กเมื่อเทียบกับความเสียหายที่เกิดขึ้นกับมือใหม่ที่ไม่สามารถเข้าใจได้ว่า x <y <z ทำอะไรได้จริง" ฉันคิดว่ามันมีประโยชน์อย่างเหลือเชื่อ อาจจะ -1 ว่า ...
แอรอนฮอลล์

หากเป้าหมายของเราคือการออกแบบภาษาที่กำจัดทุกสิ่งที่อาจสร้างความสับสนให้แก่โปรแกรมเมอร์ที่โง่ที่สุดภาษาดังกล่าวมีอยู่แล้ว: ภาษาโคบอล ฉันอยากจะใช้หลามตัวเองที่หนึ่งแน่นอนสามารถเขียนมีความหมายa < b > c < d > e < f > g "เห็นได้ชัด" (a < b) and (b > c) and (c < d) and (d > e) and (e < f) and (f > g)เพียงเพราะคุณสามารถเขียนที่ไม่ได้หมายความว่าคุณควร การกำจัดสิ่งประหลาดเหล่านี้คือขอบเขตของการตรวจสอบโค้ด ในทางกลับกันการเขียนด้วยภาษา0 < x < 8ไพ ธ อนมีความชัดเจน (ไม่มีคำพูดที่น่ากลัว) หมายความว่า x อยู่ระหว่าง 0 ถึง 8 ซึ่งเป็นเอกสิทธิ์
David Hammen

@ DavidHammen แดกดัน COBOL แน่นอนอนุญาตให้ <b <c
JoelFan

10

ในภาษาการเขียนโปรแกรมจำนวนมากx < yเป็นนิพจน์ไบนารีที่ยอมรับตัวถูกดำเนินการสองตัวและประเมินผลเป็นผลบูลีนเดี่ยว ดังนั้นหากผูกมัดหลายนิพจน์true < zและfalse < zไม่สมเหตุสมผลและหากนิพจน์เหล่านั้นประเมินผลสำเร็จพวกเขามีแนวโน้มที่จะให้ผลลัพธ์ที่ผิด

มันง่ายกว่าที่คิดว่าx < yเป็นการเรียกใช้ฟังก์ชันที่รับสองพารามิเตอร์และสร้างผลลัพธ์บูลีนเดี่ยว ในความเป็นจริงแล้วนั่นคือจำนวนภาษาที่ใช้งานภายใต้ประทุน มันแต่งได้รวบรวมได้ง่ายและใช้งานได้

x < y < zสถานการณ์มีความซับซ้อนมากขึ้น ตอนนี้คอมไพเลอร์ในผล, มีแฟชั่นสามฟังก์ชั่น: x < y, y < zและผลของทั้งสองค่า ANDed กันทั้งหมดภายในบริบทของเนื้อหาไวยากรณ์ภาษาคลุมเครือ

ทำไมพวกเขาถึงทำอย่างอื่น? เพราะมันเป็นไวยากรณ์ที่ชัดเจนง่ายต่อการใช้และง่ายต่อการแก้ไขให้ถูกต้อง


2
หากคุณกำลังออกแบบภาษาคุณมีโอกาสที่จะทำให้มันเป็นผลลัพธ์ที่ถูกต้อง
JesseTG

2
แน่นอนมันตอบคำถาม หากคำถามคือสาเหตุที่แท้จริงคำตอบคือ "เพราะนั่นคือสิ่งที่นักออกแบบภาษาเลือก" หากคุณสามารถหาคำตอบที่ดีกว่าไปได้ โปรดทราบว่า Gnasher เป็นหลักกล่าวว่าสิ่งเดียวกันในวรรคแรกของคำตอบของเขา
Robert Harvey

3
อีกครั้งที่คุณแยกผม โปรแกรมเมอร์มักจะทำเช่นนั้น "คุณต้องการนำถังขยะออกไปหรือไม่" "ไม่" "คุณจะนำถังขยะออกไปหรือไม่" "ใช่."
Robert Harvey

2
ฉันยังประกวดย่อหน้าสุดท้าย Python รองรับการเปรียบเทียบกลุ่มและตัวแยกวิเคราะห์คือ LL (1) ไม่จำเป็นต้องกำหนดและใช้ซีแมนทิกส์อย่างหนักเช่นกัน: Python เพิ่งบอกว่าe1 op1 e2 op2 e3 op3 ...เทียบเท่ากับe1 op e2 and e2 op2 e3 and ...ยกเว้นว่าแต่ละนิพจน์ได้รับการประเมินเพียงครั้งเดียว (BTW กฎง่าย ๆ นี้มีผลข้างเคียงที่ทำให้สับสนซึ่งงบที่a == b is Trueไม่มีผลกระทบที่ตั้งใจไว้อีกต่อไป)

2
@ RobertHarvey re:answerนี่คือที่ใจของฉันไปทันทีเช่นกันสำหรับความคิดเห็นของฉันในคำถามหลัก ฉันไม่ได้พิจารณาการสนับสนุนx < y < zเพื่อเพิ่มคุณค่าเฉพาะให้กับความหมายของภาษา (x < y) && (y < z)ได้รับการสนับสนุนในวงกว้างมากขึ้นมีการอธิบายมากขึ้นแสดงออกได้ง่ายขึ้นย่อยสลายได้ง่ายขึ้นเป็นองค์ประกอบของมันประกอบได้มากขึ้นมีเหตุผลมากขึ้นและปรับโครงสร้างได้ง่ายขึ้น
K. Alan Bates

6

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

ตอนนี้เรามาดูกันว่าเราจะใช้งานอย่างไร

a < b < c

เราสามารถประเมินจากซ้ายไปขวาอย่างเคร่งครัด (เชื่อมโยงซ้าย):

a.__lt__(b).__lt__(c)

แต่ตอนนี้เราเรียก__lt__ผลการซึ่งเป็นa.__lt__(b) Booleanมันไม่สมเหตุสมผลเลย

ลองเชื่อมโยงที่ถูกต้องกัน:

a.__lt__(b.__lt__(c))

ไม่นั่นไม่สมเหตุสมผลเลย a < (something that's a Boolean)ขณะนี้เรามี

โอเคสิ่งที่เกี่ยวกับการรักษามันเป็นน้ำตาลเชิงซ้อน ลอง<เปรียบเทียบการเปรียบเทียบn ส่ง 1-n-ary นี่อาจหมายถึงเราส่งข้อความ__lt__ไปให้aผ่านbและcเป็นข้อโต้แย้ง:

a.__lt__(b, c)

โอเคทำงานได้ แต่มีความไม่สมดุลแปลก ๆ ที่นี่: aตัดสินใจว่ามันจะน้อยกว่าbหรือเปล่า แต่bไม่ได้รับการตัดสินใจไม่ว่าจะเป็นน้อยกว่าcแทนว่าการตัดสินใจจะยังaทำโดย

สิ่งที่เกี่ยวกับการตีความมันเป็นข้อความที่ส่งไปยัง nary this?

this.__lt__(a, b, c)

ที่สุด! สิ่งนี้สามารถทำงานได้ มันหมายถึงว่าการเรียงลำดับของวัตถุนั้นไม่ใช่สมบัติของวัตถุอีกต่อไป (เช่นว่าaน้อยกว่าbจะไม่ใช่สมบัติของaหรือของb) แต่แทนที่จะเป็นสมบัติของบริบท (เช่นthis)

จากมุมมองหลักที่ดูแปลก ๆ อย่างไรก็ตามเช่นใน Haskell นั่นเป็นเรื่องปกติ สามารถมีการใช้งานที่แตกต่างกันหลายอย่างของOrdtypeclass เช่นและไม่ว่าaจะน้อยกว่าหรือไม่bขึ้นอยู่กับอินสแตนซ์ของ typeclass ที่เกิดขึ้นในขอบเขต

แต่จริงๆแล้วมันไม่ได้เป็นที่แปลกที่ทุกคน! ทั้ง Java ( Comparator) และ. NET ( IComparer) มีอินเทอร์เฟซที่ช่วยให้คุณสามารถฉีดความสัมพันธ์ในการสั่งซื้อของคุณเองลงไปเช่นขั้นตอนวิธีการเรียงลำดับ ดังนั้นพวกเขายอมรับอย่างเต็มที่ว่าการสั่งซื้อไม่ใช่สิ่งที่ถูกกำหนดเป็นประเภท แต่ขึ้นอยู่กับบริบท

เท่าที่ฉันรู้ในปัจจุบันไม่มีภาษาที่ใช้ทำการแปลดังกล่าว อย่างไรก็ตามมีความสำคัญกว่า: ทั้งIokeและSephมีสิ่งที่นักออกแบบเรียกว่า "ตัวดำเนินการ trinary" - ตัวดำเนินการซึ่งเป็นไบนารีsyntacticallyแต่มีความหมายสามส่วน โดยเฉพาะอย่างยิ่ง,

a = b

จะไม่ได้ตีความว่าการส่งข้อความ=เพื่อaส่งผ่านbเป็นอาร์กิวเมนต์ แต่การส่งข้อความ=ไปที่ "กราวนด์ในปัจจุบัน" (แนวคิดที่คล้ายกัน แต่ไม่เหมือนกันthis) ผ่านaและbเป็นข้อโต้แย้ง ดังนั้นจึงa = bตีความได้ว่า

=(a, b)

และไม่

a =(b)

สิ่งนี้สามารถนำไปใช้กับผู้ประกอบการ n-ary ได้อย่างง่ายดาย

โปรดทราบว่านี่เป็นเรื่องแปลกสำหรับภาษา OO ใน OO เรามักจะมีวัตถุหนึ่งชิ้นซึ่งท้ายที่สุดรับผิดชอบในการตีความการส่งข้อความและในขณะที่เราได้เห็นมันไม่ชัดเจนในทันทีสำหรับบางสิ่งเช่นa < b < cวัตถุที่ควรจะเป็น

สิ่งนี้ไม่ได้ใช้กับขั้นตอนหรือภาษาที่ใช้งานได้ ยกตัวอย่างเช่นในโครงการ , Common เสียงกระเพื่อมและClojureที่<ฟังก์ชั่น N-Ary และสามารถเรียกว่ามีจำนวนข้อของการขัดแย้ง

โดยเฉพาะอย่างยิ่ง<ไม่ได้หมายความว่า "น้อยกว่า" แต่ฟังก์ชั่นเหล่านี้จะตีความแตกต่างกันเล็กน้อย:

(<  a b c d) ; the sequence a, b, c, d is monotonically increasing
(>  a b c d) ; the sequence a, b, c, d is monotonically decreasing
(<= a b c d) ; the sequence a, b, c, d is monotonically non-decreasing
(>= a b c d) ; the sequence a, b, c, d is monotonically non-increasing

3

เป็นเพราะนักออกแบบภาษาไม่ได้คิดหรือไม่คิดว่ามันเป็นความคิดที่ดี Python ทำตามที่คุณอธิบายด้วยไวยากรณ์ (เกือบ) LL (1) อย่างง่าย


1
นี้จะยังคงแยกกับไวยากรณ์ปกติในภาษากระแสหลักค่อนข้างมาก จะไม่สามารถเข้าใจได้อย่างถูกต้องด้วยเหตุผลที่ @RobertHarvey มอบให้
Mason Wheeler

@MasonWheeler ไม่ไม่จำเป็น หากกฎถูกเขียนขึ้นเพื่อให้การเปรียบเทียบสามารถใช้แทนกันได้กับตัวดำเนินการอื่น (พูดเพราะมีความสำคัญเท่ากัน) คุณจะไม่ได้รับพฤติกรรมที่เหมาะสม ความจริงที่ว่า Python ทำการเปรียบเทียบทั้งหมดในระดับเดียวคือสิ่งที่อนุญาตให้มันปฏิบัติต่อลำดับเป็นการรวมกัน
Neil G

1
ไม่ได้จริงๆ ใส่1 < 2 < 3ลงใน Java หรือ C # และคุณไม่ได้มีปัญหากับความสำคัญของโอเปอเรเตอร์ คุณมีปัญหากับประเภทที่ไม่ถูกต้อง ปัญหาคือว่าสิ่งนี้จะยังคงแยกวิเคราะห์ตามที่คุณเขียน แต่คุณต้องใช้ตรรกะกรณีพิเศษในคอมไพเลอร์เพื่อเปลี่ยนจากลำดับการเปรียบเทียบรายบุคคลเป็นการเปรียบเทียบที่ถูกโยง
Mason Wheeler

2
@MasonWheeler สิ่งที่ฉันพูดคือภาษานั้นต้องได้รับการออกแบบมาให้ใช้งานได้ ส่วนหนึ่งของการได้รับไวยากรณ์ที่ถูกต้อง (หากกฎถูกเขียนขึ้นเพื่อให้การเปรียบเทียบสามารถใช้แทนกันได้กับตัวดำเนินการอื่นพูดเพราะพวกมันมีลำดับความสำคัญเท่ากันคุณจะไม่ได้พฤติกรรมที่เหมาะสม) อีกส่วนหนึ่งของการตีความ AST เป็นร่วมซึ่ง C ++ ไม่ทำ ประเด็นหลักของคำตอบคือการตัดสินใจของนักออกแบบภาษา
Neil G

@MasonWheeler ฉันคิดว่าเราเห็นด้วย ฉันแค่เน้นว่ามันไม่ยากที่จะได้ไวยากรณ์ที่ถูกต้องสำหรับเรื่องนี้ มันเป็นเรื่องของการตัดสินใจล่วงหน้าว่าคุณต้องการให้มันทำงานแบบนี้
Neil G

2

โปรแกรม C ++ ต่อไปนี้คอมไพล์ด้วย nary peep จากเสียงดังกราวแม้จะมีคำเตือนตั้งไว้ในระดับสูงสุดที่เป็นไปได้ ( -Weverything):

#include <iostream>
int main () { std::cout << (1 < 3 < 2) << '\n'; }

ชุดคอมไพเลอร์ gnu ในทางตรงกันข้ามเตือนฉันcomparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]อย่างนั้น

ดังนั้นคำถามของฉันคือ: ทำไม x <y <z โดยทั่วไปไม่สามารถใช้งานได้ในภาษาโปรแกรมด้วยซีแมนทิกส์ที่คาดหวัง?

คำตอบนั้นง่าย: ความเข้ากันได้ย้อนหลัง มีโค้ดจำนวนมากอยู่ใน wild ที่ใช้สิ่งที่เทียบเท่า1<3<2และคาดว่าผลลัพธ์จะเป็นจริง

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


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

@SethBattin - นี่ไม่ใช่ฝันร้ายในการดีบักใน Python ปัญหาเดียวใน Python ก็คือif x == y is True : ...ความคิดเห็นของฉัน: ผู้ที่เขียนโค้ดประเภทนั้นสมควรที่จะได้รับการทรมานพิเศษที่พิเศษและพิเศษซึ่งถ้าเขายังมีชีวิตอยู่ในปัจจุบัน) จะทำให้ Torquemada เป็นลม
David Hammen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.