อะไรทำให้โอเปอเรเตอร์ของ Scala โอเวอร์โหลด“ ดี” แต่ C ++ ของ“ ไม่ดี”?


155

ผู้ประกอบการมากไปใน C ++ นั้นหลายคนคิดว่าเป็นสิ่งไม่ดี (tm) และความผิดพลาดที่ไม่ควรทำซ้ำในภาษาที่ใหม่กว่า แน่นอนว่ามันเป็นคุณสมบัติหนึ่งที่ลดลงโดยเฉพาะเมื่อออกแบบ Java

ตอนนี้ฉันเริ่มอ่าน Scala ฉันพบว่ามันมีลักษณะเหมือนตัวดำเนินการมากเกินไป (แม้ว่าในทางเทคนิคแล้วมันไม่มีตัวดำเนินการมากไปเพราะมันไม่มีตัวดำเนินการฟังก์ชันเท่านั้น) อย่างไรก็ตามดูเหมือนว่าจะไม่แตกต่างจากผู้ประกอบการมากไปใน C ++ ซึ่งผมจำได้ว่าผู้ประกอบการได้รับการกำหนดให้เป็นฟังก์ชั่นพิเศษ

ดังนั้นคำถามของฉันคืออะไรทำให้แนวคิดของการกำหนด "+" ใน Scala เป็นความคิดที่ดีกว่าใน C ++


27
ทั้ง C ++ ไม่ใช่ Scala ถูกกำหนดโดยฉันทามติสากลในบรรดาโปรแกรมเมอร์ทั้งหมด ฉันไม่คิดว่าจะมีข้อขัดแย้งใด ๆ ระหว่างความจริงที่ว่าบางคนโหยหาเกี่ยวกับ C ++ และความจริงที่ว่าบางคนไม่ได้ฟังเกี่ยวกับ Scala
Steve Jessop

16
ไม่มีอะไรเลวร้ายเกี่ยวกับการใช้งานเกินพิกัดใน C ++
ลูกสุนัข

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

Scala ได้รับการออกแบบเหมือนทศวรรษหลังจาก c ++ ปรากฎว่าคนที่อยู่เบื้องหลังมันเป็นคนฉลาดในแง่ของการเขียนโปรแกรมภาษา ไม่มีอะไรเลวร้ายถ้าคุณใช้ c ++ หรือ Scala ต่อไปอีก 100 ปีเห็นได้ชัดว่าอาจเป็นได้ทั้งคู่! เห็นได้ชัดว่ามีอคติอยู่ในธรรมชาติของเรา แต่เราสามารถต่อสู้กับมันได้เพียงแค่ดูประวัติของเทคโนโลยีทุกอย่างล้าสมัย
Nader Ghanbari

คำตอบ:


242

C ++ สืบทอดตัวดำเนินการสีน้ำเงินที่แท้จริงจาก C โดยที่ฉันหมายความว่า "+" ใน 6 + 4 นั้นพิเศษมาก เช่นคุณไม่สามารถรับตัวชี้ไปยังฟังก์ชัน +

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

สิ่งที่คุณต้องการเรียกมันว่าการบรรทุกเกินพิกัดไม่ได้เลวร้ายอย่างแท้จริงแม้แต่ใน C ++ ปัญหาคือเมื่อโปรแกรมเมอร์ไม่ดีใช้งานในทางที่ผิด แต่ตามความจริงแล้วฉันเห็นว่าการกำจัดความสามารถของโปรแกรมเมอร์ในการละเมิดผู้ปฏิบัติงานมากเกินไปไม่ได้ทำให้การแก้ไขทุกสิ่งที่โปรแกรมเมอร์สามารถทำได้ คำตอบที่แท้จริงคือการให้คำปรึกษา http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html

ไม่มีความแตกต่างระหว่างตัวดำเนินการโอเวอร์โหลดของ C ++ กับวิธีการตั้งชื่อแบบยืดหยุ่นของ Scala ซึ่ง IMHO ทำให้ Scala มีทั้งที่ใช้งานไม่ได้และใช้งานได้มากกว่า

ใน C ++ วิธีเดียวที่จะได้รับเครื่องหมายการแก้ไขคือการใช้ตัวดำเนินการ มิฉะนั้นคุณต้องใช้ object.message (อาร์กิวเมนต์) หรือตัวชี้ -> messsage (อาร์กิวเมนต์) หรือฟังก์ชั่น (argument1, argument2) ดังนั้นหากคุณต้องการสไตล์ DSLish บางอย่างกับรหัสของคุณแล้วมีความกดดันในการใช้โอเปอเรเตอร์

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

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

Scala อนุญาตให้มีสัญลักษณ์ที่ไม่ใช่คำที่ถูกต้องเป็นชื่อวิธี ตัวอย่างเช่นฉันมี DSL Prolog-ish ในตัวที่คุณสามารถเขียนได้

female('jane)!         // jane is female
parent('jane,'john)!   // jane is john's parent
parent('jane, 'wendy)! // jane is wendy's parent

mother('Mother, 'Child) :- parent('Mother, 'Child) & female('Mother) //'// a mother of a child is the child's parent and is female

mother('X, 'john)?  // find john's mother
mother('jane, 'X)?  // find's all of jane's children

สัญลักษณ์: -,!,?, และ & ถูกกำหนดเป็นวิธีการทั่วไป ใน C ++ เท่านั้น & จะใช้ได้ดังนั้นความพยายามในการจับคู่ DSL นี้กับ C ++ จะต้องใช้สัญลักษณ์บางอย่างที่ทำให้เกิดแนวคิดที่แตกต่างกันอยู่แล้ว

แน่นอนว่านี่เป็นการเปิด Scala ให้เป็นการละเมิดอีกประเภทหนึ่ง ใน Scala คุณสามารถตั้งชื่อวิธีการ $! & ^% หากคุณต้องการ

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


ฉันได้ตรวจสอบครั้งล่าสุดแล้วผู้ปฏิบัติงาน + (5) ใช้งานได้ ฉันประหลาดใจจริง ๆ ที่ & (3.operator +) ไม่
Joshua

ตัวอย่างเช่นคุณสามารถทำ assert (female ("jane")) ใน c ++ ที่จะไม่สับสนเลย - พยักหน้ากลับไปที่โพสต์ james-iry เกี่ยวกับมันไม่ได้เป็นผู้ประกอบการที่ + เป็นสิ่งที่ไม่ดี แต่โปรแกรมเมอร์โง่เป็น
pm100

1
@Joshua ให้int main() {return (3).operator+(5);}ผลลัพธ์ในerror: request for member ‘operator+’ in ‘3’, which is of non-class type ‘int’
zildjohn01

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

@JukkaDahlbom การดำรงอยู่ของพอยน์เตอร์อัจฉริยะทำให้เกิดประโยชน์มากมายในตัวมันเอง แล้วคุณมี lambdas, ประเภทตัวเลขที่ผู้ใช้กำหนด, ประเภทช่วงเวลา ...
Alexey Romanov

66

ผู้ประกอบการมากไปใน C ++ นั้นหลายคนคิดว่าเป็นสิ่งที่ไม่ดี (tm)

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


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

16
+1 ผู้ประกอบการมากไปใน C ++ เป็นสิ่งที่ดี ยกตัวอย่างเช่นมันทำให้เวกเตอร์คณิตศาสตร์สะอาดขึ้นมาก เช่นเดียวกับฟีเจอร์ C ++ มากมายคุณควรใช้พลังงานอย่างระมัดระวัง
John Smith

7
@Kristo เพราะ C ++ ใช้ค่าที่ต้องกำหนดและคัดลอก มีความจำเป็นต้องควบคุมสิ่งนั้นดังนั้นคุณจะต้องสามารถระบุตัวดำเนินการที่ได้รับมอบหมายสำหรับประเภทที่กำหนดอย่างน้อยที่สุด

7
@Kristo: เพราะเจตนาหนึ่งของ C ++ คือการอนุญาตให้ผู้ใช้กำหนดประเภทที่จะทำทุกอย่างที่มีอยู่ภายในประเภท (แม้ว่าพวกเขาจะได้รับการปฏิบัติที่แตกต่างกันในบริบทบางอย่างเช่นการแปลงโดยนัย) หากคุณต้องการใช้จำนวนเต็ม 27 บิตคุณสามารถทำได้และการใช้มันจะเหมือนกับการใช้ int หากไม่มีตัวดำเนินการมากเกินไปมันจะไม่สามารถใช้ UDT ที่มีไวยากรณ์เหมือนกับชนิดบิวด์อินได้ดังนั้นภาษาผลลัพธ์จะไม่เหมือน "C ++" ในแง่นี้
Steve Jessop

8
"นั่นเป็นวิธีที่บ้า" - ยิ่งแย่กว่านั้นคือ std :: vector <bool>!
Steve Jessop

42

การบรรทุกเกินพิกัดของผู้ปฏิบัติงานไม่เคยคิดในระดับสากลว่าเป็นความคิดที่ไม่ดีใน C ++ - เพียงแค่การละเมิดการใช้งานเกินกำลังที่คิดว่าเป็นความคิดที่ไม่ดี ไม่มีใครต้องการผู้ปฏิบัติงานมากไปในภาษาเพราะพวกเขาสามารถจำลองด้วยฟังก์ชั่น verbose เพิ่มเติมได้ การหลีกเลี่ยงการโอเวอร์โหลดของผู้ปฏิบัติงานใน Java ทำให้การนำไปปฏิบัติและข้อกำหนดของ Java นั้นง่ายขึ้นเล็กน้อย มีการถกเถียงกันในชุมชน Java เกี่ยวกับการแนะนำตัวดำเนินการมากไป

ข้อดีและข้อเสียของการใช้งานเกินพิกัดใน Scala เหมือนกับใน C ++ - คุณสามารถเขียนรหัสธรรมชาติมากขึ้นถ้าคุณใช้การบรรทุกเกินพิกัดอย่างเหมาะสม - และรหัสที่คลุมเครือและสับสนหากคุณไม่ทำ

FYI: ผู้ประกอบการไม่ได้กำหนดไว้เป็นฟังก์ชั่นพิเศษใน C ++ พวกเขาทำงานเหมือนฟังก์ชั่นอื่น ๆ - แม้ว่าจะมีความแตกต่างบางประการในการค้นหาชื่อไม่ว่าพวกเขาจะต้องเป็นสมาชิกฟังก์ชันและความจริงที่ว่าพวกเขาสามารถเรียกได้สองวิธี: 1 ) ตัวดำเนินการไวยากรณ์และ 2) ไวยากรณ์ตัวดำเนินการ -ID


"ผู้ใช้ไม่จำเป็นต้องใช้งานมากเกินไปในภาษาเนื่องจากสามารถจำลองด้วยฟังก์ชั่น verbose เพิ่มเติมได้" ไม่มีใครต้องการผู้ประกอบการภายใต้ตรรกะนั้น ทำไมไม่ใช้เพียงadd(2, multiply(5, 3))?
Joe Z.

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

19

บทความนี้ - " The Positive Legacy ของ C ++ และ Java " - ตอบคำถามของคุณโดยตรง

"C ++ มีทั้งการจัดสรรสแต็กและการจัดสรรฮีปและคุณต้องโอเวอร์โหลดโอเปอเรเตอร์ของคุณเพื่อจัดการกับทุกสถานการณ์และไม่ทำให้หน่วยความจำรั่วไหลยากจริง ๆ อย่างไรก็ตาม Java มีกลไกการจัดสรรหน่วยเก็บข้อมูลเดียว ..

Java ผิดพลาด (อ้างอิงจากผู้เขียน) ละเว้นโอเปอเรเตอร์การบรรทุกเกินพิกัดเนื่องจากมีความซับซ้อนใน C ++ แต่ลืมไปว่าทำไม (หรือไม่ทราบว่าไม่ได้ใช้กับ Java)

โชคดีที่ภาษาระดับสูงกว่าเช่น Scala ให้ตัวเลือกสำหรับนักพัฒนาในขณะที่ยังคงใช้งาน JVM เดียวกัน


14
Eckel เป็นแหล่งเดียวที่ฉันเคยเห็นสำหรับความคิดที่ว่าตัวดำเนินการมากเกินไปถูกทิ้งจาก Java เนื่องจากภาวะแทรกซ้อนใน C ++ และเขาไม่ได้บอกว่าแหล่งที่มาของเขาคืออะไร ฉันจะลดราคา แหล่งข้อมูลอื่น ๆ ทั้งหมดที่ฉันบอกว่ามันถูกทิ้งเนื่องจากอาจมีการละเมิด ดูgotw.ca/publications/c_family_interview.htmและnewt.com/wohler/articles/james-gosling-ramblings-1.html เพียงค้นหาหน้าพวกเขาเพื่อ "โอเปอเรเตอร์การบรรทุกเกินพิกัด"
James Iry

9

ไม่มีอะไรผิดปกติกับการใช้งานเกินกำลัง ในความเป็นจริงมีบางอย่างผิดปกติหากไม่มีตัวดำเนินการมากเกินไปสำหรับชนิดตัวเลข (ดูที่โค้ด Java บางตัวที่ใช้ BigInteger และ BigDecimal)

C ++ มีธรรมเนียมในการใช้คุณลักษณะนี้อย่างไม่เหมาะสม ตัวอย่างที่อ้างถึงบ่อยครั้งคือตัวดำเนินการ bitshift โอเวอร์โหลดเพื่อทำ I / O


<< และ >> โอเปอเรเตอร์กำลังแสดงวิธีการถ่ายโอนด้วยสายตาพวกเขาตั้งใจจะทำ I / O ไม่ใช่การละเมิดมันมาจากห้องสมุดมาตรฐานและสิ่งที่ใช้งานได้จริง แค่ดูที่ "cin >> บางอย่าง" อะไรจะไปไหน จากซินไปจนถึงบางสิ่ง
peenut

7
@peenut: แต่การใช้งานเดิมของพวกเขาเปลี่ยนไปเล็กน้อย "ไลบรารีมาตรฐาน" ใช้ตัวดำเนินการในลักษณะที่ยุ่งเหยิงกับคำจำกัดความดั้งเดิมอย่างสมบูรณ์
Joe Z.

1
ฉันแน่ใจว่าฉันได้อ่านที่ไหนสักแห่งที่ Bjarne Stroustrup (ผู้สร้าง C ++) ทดลองใช้=แทน<<และ>>ในวันแรก ๆ ของ C ++ แต่พบปัญหาเพราะไม่มีตัวดำเนินการที่เหมาะสม (เช่นมองหา อาร์กิวเมนต์ด้านซ้ายหรือขวาก่อน) ดังนั้นมือของเขาจึงถูกมัดเล็กน้อยเกี่ยวกับสิ่งที่เขาสามารถใช้ได้
Phil Wright

8

โดยทั่วไปแล้วมันไม่ใช่เรื่องเลวร้าย
ภาษาใหม่เช่น C # ยังมีตัวดำเนินการมากไป

มันเป็นการละเมิดผู้ปฏิบัติงานเกินพิกัดที่เป็นสิ่งที่ไม่ดี

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

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

ความจริงที่ว่า + - * / all คืนค่าชนิดเดียวกันกับที่พวกเขาทำงาน (หลังจากเลื่อนขั้นโอเปอเรเตอร์)
เวอร์ชันที่โอเวอร์โหลดสามารถส่งคืนสิ่งใดก็ได้ (นี่คือจุดที่มีการละเมิดในกรณีที่ผู้ประกอบการของคุณ สิ่งที่ลงเขา)


8

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

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


6

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

ในเวลาเดียวกันการพูดคุยครั้งนี้เป็นแรงบันดาลใจให้มีงานวิจัยพื้นฐานมากมายรวมถึง Scala ซึ่งเป็นหนึ่งในเอกสารที่ทุกคนควรอ่านเพื่อทำงานในสาขานี้

กลับไปยังจุดที่ตัวอย่างของเขาส่วนใหญ่เกี่ยวกับชั้นเรียนตัวเลข (เช่น BigInteger และบางสิ่งที่แปลกประหลาด) แต่นั่นไม่จำเป็น

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


4

ฉันเชื่อว่าคำตอบทุกข้อพลาดไป ใน C ++ คุณสามารถโอเวอร์โหลดโอเปอเรเตอร์ทั้งหมดที่คุณต้องการ แต่คุณไม่สามารถให้ความสำคัญกับสิ่งที่พวกเขากำลังประเมิน สกาล่าไม่มีปัญหานี้ IIRC

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


1
สกาล่าได้แก้ไขลำดับความสำคัญของโอเปอเรเตอร์เช่นกันใช่ไหม
skaffman

ฉันเชื่อว่ามี แต่มันประจบประแจงไกล มากกว่าที่จุด Scala มีผู้ประกอบการน้อยกว่าระยะเวลา +, -, * เป็นวิธีการไม่ใช่ตัวดำเนินการ IIRC ซึ่งเป็นสาเหตุที่ 2 + 3 * 2 ไม่ใช่ 8 คือ 10
Saem

7
Scala มีระบบที่มีลำดับความสำคัญตามอักขระตัวแรกของสัญลักษณ์ สกาล่า> 2 + 3 * 2 res0: Int = 8
James Iry

3

การบรรทุกเกินพิกัดของผู้ประกอบการไม่ใช่สิ่งประดิษฐ์ C ++ - มาจาก Algol IIRC และแม้แต่ Gosling ก็ไม่ได้อ้างว่าเป็นความคิดที่ไม่ดีโดยทั่วไป


แน่นอน แต่มันอยู่ในชาติ C ++ ของมันที่ได้รับอากาศทั่วไปของความน่าเชื่อถือ
skaffman

5
คุณหมายถึงอะไรโดย "อากาศทั่วไปแห่งความไม่น่าไว้วางใจ" คนส่วนใหญ่ที่ฉันรู้จักใช้ภาษาที่รองรับการใช้งานเกินพิกัด (C ++, C #) และฉันไม่เคยได้ยินเรื่องร้องเรียนเลย
Nemanja Trifunovic

ฉันพูดจากประสบการณ์ที่ยาวนานของฉันกับ pre-ANSI C ++ และฉันจำได้ว่าไม่ชอบพวกเขา บางทีสถานการณ์ดีขึ้นด้วย ANSI C ++ หรือผู้คนเพิ่งเรียนรู้วิธีที่จะไม่ละเมิด
skaffman

1
การพูดในฐานะคนที่ใช้ C ++ มาตั้งแต่ช่วง cfront day (กลาง 80s) ผมรับรองได้เลยว่าการแนะนำมาตรฐาน ISO นั้นไม่มีผลกระทบต่ออคติของผู้คนเกี่ยวกับการใช้งานเกินกำลัง

3

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


2

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

ลูกค้าได้ทราบวิธีประเภทเช่น int ประพฤติดังนั้นคุณควรมุ่งมั่นที่จะมีชนิดของคุณประพฤติในทางเดียวกันเมื่อใดก็ตามที่เหมาะสม ... เมื่อสงสัยทำตาม ints ทำ (จากรายการ C ++ รุ่น 3 ที่มีประสิทธิภาพ 18)

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


ฉันไม่ได้โต้เถียงหรือต่อต้านผู้ปฏิบัติงานมากเกินไปที่นี่ฉันไม่ได้มองหาคนที่จะพิสูจน์พวกเขา
skaffman

Sprint ไม่ได้มาใกล้กับตัวอย่างที่แย่ที่สุดที่ฉันเคยเจอมา - คุณควรดูว่าไลบรารีฐานข้อมูล RogueWave ลุกขึ้นมาได้ยังไง!

ฉันยอมรับว่าวิญญาณใช้ผู้ปฏิบัติงานในทางที่ผิด แต่ฉันไม่สามารถคิดวิธีที่ดีกว่าได้
Zifre

1
ฉันไม่คิดว่าวิญญาณกำลังเหยียดหยามผู้ปฏิบัติงาน แต่มันผลักดันมัน ฉันเห็นด้วยไม่มีวิธีอื่นที่จะทำ โดยพื้นฐานแล้วมันจะสร้าง DSL ภายในไวยากรณ์ของ C ++ อยู่ไกลจากสิ่งที่ C ++ ถูกออกแบบมาให้ทำ ใช่มีตัวอย่างที่แย่ยิ่งกว่า :) โดยทั่วไปฉันใช้พวกมันตามความเหมาะสม ส่วนใหญ่เป็นเพียงตัวดำเนินการสตรีมสำหรับการดีบัก \ log และถึงแม้จะมีแค่น้ำตาลที่ส่งต่อไปยังวิธีการที่นำไปใช้ในชั้นเรียน
ราคาแมตต์

1
มันเป็นคำถามรสชาติ แต่ตัวแยกวิเคราะห์ไลบรารีของ combinator ในภาษาที่ใช้งานได้มีตัวดำเนินการโอเวอร์โหลดในลักษณะที่คล้ายกับวิญญาณมากและไม่มีใครโต้แย้งเลย มีเหตุผลทางเทคนิคมากมายที่พวกเขาทำได้ดีกว่า - Google สำหรับ "ภาษาเฉพาะโดเมนแบบฝังตัว" เพื่อค้นหาเอกสารจำนวนมากที่อธิบายว่าจากมุมมองทั่วไปและ Google สำหรับ "scala parser combinator" สำหรับตัวอย่างในทางปฏิบัติในกรณีนี้ เป็นความจริงที่ว่าในภาษาที่ใช้งานได้มักจะมีไวยากรณ์ที่ดีกว่าตัวอย่างเช่นคุณไม่จำเป็นต้องเปลี่ยนความหมายของ >> สำหรับตัวแยกวิเคราะห์ที่เชื่อมโยงกัน
Blaisorblade

2

ฉันไม่เคยเห็นบทความที่อ้างว่าการบรรทุกเกินพิกัดของ C ++ นั้นไม่ดี

โอเปอเรเตอร์ที่ผู้ใช้กำหนดเองได้ช่วยให้สามารถใช้ภาษาได้ง่ายขึ้นและชัดเจนขึ้น


1

อย่างไรก็ตามดูเหมือนว่าจะไม่แตกต่างจากผู้ประกอบการมากไปใน C ++ ซึ่งผมจำได้ว่าผู้ประกอบการได้รับการกำหนดให้เป็นฟังก์ชั่นพิเศษ

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

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