เหตุใดไลบรารีมาตรฐานจึงไม่เขียนโปรแกรมภาษาดั้งเดิม [ปิด]


30

ฉันคิดว่าเหตุใดจึงมี (ในภาษาการเขียนโปรแกรมทั้งหมดที่ฉันได้เรียนรู้เช่น C ++, Java, Python) ไลบรารีมาตรฐานอย่าง stdlib แทนที่จะมี "ฟังก์ชั่น" ที่คล้ายคลึงกันซึ่งเป็นภาษาดั้งเดิมของตัวเอง


4
คุณหมายถึงอะไร "ทำไมคอมไพเลอร์ไม่สามารถแปลการเรียกฟังก์ชันเป็นชุดคำสั่ง" ได้? นั่นคือสิ่งที่คอมไพเลอร์ทำ, ไลบรารีมาตรฐานหรือไม่ (Ok, Python เพียงบางส่วนและ Java ถึง JVM bytecode; แนวคิดที่คล้ายกัน) ไลบรารีมาตรฐานไม่มีส่วนเกี่ยวข้องกับการรวบรวมรหัส -> คำแนะนำ
Delioth

25
@Delioth ฉันคิดว่า Simone ถามว่าทำไมไม่ใช่ทุกอย่างในห้องสมุดภาษามาตรฐาน $ LANG เป็นโครงสร้าง / หน้าที่ดั้งเดิมของภาษานั้นแทน ฉันจะบอกว่ามันเป็นคำถามที่สมเหตุสมผลสำหรับทุกคนที่ยังใหม่กับภาษาโปรแกรม :)
Andres F.

33
ห้องสมุดมาตรฐานทั่วไปเติมช่องว่างระหว่างการทำงานการเขียนโปรแกรมภาษาและมีประโยชน์หนึ่งที่คนจะใช้
Telastyn

6
ส่วนสำคัญของไลบรารี่มาตรฐานของไพ ธ อนเขียนด้วย C และเรียบเรียงมา
ElmoVanKielmo

1
ในทางตรงกันข้ามการใช้งานส่วนใหญ่ของ BASIC ทุกอย่างเป็นส่วนหนึ่งของภาษาและไม่มีห้องสมุดใด ๆ ที่ไม่สนับสนุนพวกเขา (บันทึกในการนำไปใช้หลายครั้งเพื่อความสามารถในการเรียกใช้รูทีนภาษาเครื่อง)
Euro Micelli

คำตอบ:


32

ให้ฉันขยายค่อนข้างคำตอบที่ดีของ @ Vincent (+1) :

ทำไมคอมไพเลอร์ไม่เพียงแปลการเรียกฟังก์ชันเป็นชุดคำสั่ง?

มันสามารถและทำได้โดยใช้กลไกอย่างน้อยสองอย่าง:

  • การอินไลน์การเรียกใช้ฟังก์ชั่น - ในระหว่างการแปลคอมไพเลอร์สามารถแทนที่การเรียกซอร์สโค้ดด้วยการนำไปใช้โดยตรงแบบอินไลน์แทนที่จะทำการเรียกใช้ฟังก์ชันจริง ยังคงมีฟังก์ชั่นที่จะต้องมีการใช้งานที่กำหนดไว้ที่ไหนสักแห่งและที่สามารถอยู่ในห้องสมุดมาตรฐาน

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

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

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

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


3
คำตอบที่ดี เราควรเพิ่มบางคำว่าทำไมการตัดสินใจใน C นี้: ถ้าฉันจำได้อย่างถูกต้องเหตุผลหลักคือเพราะมันทำให้การสร้างคอมไพเลอร์ C ง่ายขึ้นสำหรับสถาปัตยกรรมฮาร์ดแวร์ที่แตกต่างกัน
Doc Brown

10
@DocBrown ในปี 1975 มีตัวอย่างมากมายในด้านการพัฒนาภาษาโปรแกรม (ALGOL-68, ใคร?) ซึ่งแสดงให้เห็นว่าความพยายามที่จะอบทุกอย่างลงในภาษาโดยตรงทำให้เกิดการชะลอตัวลงอย่างมากทั้งในการกำหนดภาษาและ ในการผลิตการใช้งานภาษา
Joker_vD

5
ตัวอย่างที่คล้ายกันคือสิ่งที่ Python ทำกับprint: ใน 2.x มันเป็นข้อความที่มีไวยากรณ์พิเศษของมันเอง แต่ใน 3.x มันกลายเป็นเพียงการเรียกใช้ฟังก์ชันอื่น ดูPEP 3105สำหรับคำอธิบายอย่างเป็นทางการ
dan04

1
@DocBrown การพกพานั้นแทบจะไม่มีเหตุผล เมื่อสร้าง Unix และ C พวกเขาได้รับการออกแบบและสร้างขึ้นสำหรับเครื่องจักรหนึ่งเครื่อง PDP-7 ที่เหมือนกับ Ken Thompson ที่สงสัยว่าแนวคิดใดที่สามารถกู้คืนได้จากโครงการ Multics ที่ล้มเหลว C ถูกสร้างขึ้นด้วยเหตุผลหนึ่งประการ: เพื่อให้มีภาษาระดับสูงที่จะใช้ Unix โดยพื้นฐานแล้วเรากำลังทำการทดลองในการออกแบบซอฟต์แวร์ไม่ใช่ความพยายามอย่างจริงจังในระบบปฏิบัติการหลายแพลตฟอร์มและภาษา ดูbell-labs.com/usr/dmr/www/chist.htmlตัวอย่างเช่น
Euro Micelli

@EuroMicelli: ฉันไม่เห็นมีความขัดแย้ง และการอ้างอิงของคุณมีรายละเอียดมากมายเกี่ยวกับเวลาที่การพกพามีความสำคัญจริง ๆ แล้วในช่วงปีแรก ๆ ของการพัฒนา C และ Unix ฉันเดาได้เฉพาะที่นี่ แต่ถ้านักประดิษฐ์ C จะไม่ใช้ภาษาเล็ก ๆ อย่างตั้งใจฉันคิดว่าคงไม่น่าเป็นไปได้เลยที่พวกเขาจะได้รับการแจ้งเตือนอย่างรวดเร็วและประสบความสำเร็จกับสถาปัตยกรรมที่แตกต่างกัน
Doc Brown

70

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

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


3
ไม่เสมอ. PHPเป็นตัวอย่างแทบจะไม่ทำให้ความแตกต่างระหว่างฟังก์ชั่นภาษาที่กว้างใหญ่และภาษาของมันเอง
Vahid Amiri

15
ฉันจะไม่ใช้ PHP เป็นตัวอย่างของภาษาง่ายๆ
DrBreakalot

3
@DrBreakalot PHP เป็นอย่างยิ่งภาษาที่ง่าย ไม่ได้หมายความว่ามันมีการออกแบบที่สอดคล้องกัน แต่เป็นอีกปัญหาหนึ่ง
การแข่งขัน Lightness กับโมนิก้า

19
@LightnessRacesinOrbit ฉันจะไม่เรียก PHP ว่า "ง่าย" เลย: มันมีระบบอ็อบเจกต์คลาส, ชุดของ 'ค่าดั้งเดิม', ฟังก์ชั่นแบบสแตนด์อโลน, การปิดคลาสแรกที่สร้างขึ้นบนระบบวัตถุ, กลไกเนมสเปซต่างๆ ความคิดที่เรียกว่า "คงที่" งบเช่นเดียวกับสำนวนinclude, requireและrequire_onceถ้า / สำหรับ / ขณะที่ (การเขียนโปรแกรมโครงสร้าง) ข้อยกเว้นระบบที่แยกต่างหากของค่าความผิดพลาด 'ซับซ้อนกฎการพิมพ์อ่อนแอซับซ้อนกฎสำคัญประกอบและในและใน . เปรียบเทียบสิ่งนี้กับความเรียบง่ายของการพูด, Smalltalk, Scheme, Prolog, Forth, ฯลฯ ;)
Warbo

3
เหตุผลหลักที่บอกเป็นนัย แต่ไม่ได้ระบุไว้อย่างชัดเจนในคำตอบนี้ก็คือการทำให้ภาษาเรียบง่ายที่สุดเท่าที่จะเป็นไปได้มันง่ายกว่าที่จะนำไปใช้กับแพลตฟอร์มอื่น เนื่องจากไลบรารีมาตรฐานมักจะเขียนด้วยภาษาเองพวกเขาจึงสามารถจัดวางได้เล็กน้อย
BlueRaja - Danny Pflughoeft

34

นอกเหนือจากคำตอบอื่น ๆ ที่ได้กล่าวไปแล้วการใส่ฟังก์ชั่นมาตรฐานลงในห้องสมุดก็คือการแยกข้อกังวล :

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

  • มันเป็นงานของห้องสมุดมาตรฐาน (เป็นงานที่มีอยู่โดยปริยายเสมอ) เพื่อให้ฟังก์ชันการทำงานหลักที่โปรแกรมทุกโปรแกรมต้องการ ไม่ใช่หน้าที่ของห้องสมุดมาตรฐานที่จะมีฟังก์ชั่นทั้งหมดที่อาจมีประโยชน์

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

  • เป็นหน้าที่ของไลบรารีผู้ใช้ในการจัดหาคอลเลกชันของฟังก์ชั่นที่ใช้ซ้ำได้ที่มีประโยชน์ ไม่ใช่หน้าที่ของไลบรารีผู้ใช้ที่จะมีรหัสทั้งหมดที่เคยเขียน

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

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

  • เธรดไลบรารีนั้นไม่มีค่าบนคอนโทรลเลอร์แบบฝังคอร์ การอนุญาตให้ใช้งานภาษาสำหรับคอนโทรลเลอร์แบบฝังนี้ไม่รวมpthreadไลบรารีเป็นเพียงสิ่งที่ถูกต้อง

  • ห้องสมุดคณิตศาสตร์ไม่มีค่าใน micro-controller ที่ไม่มี FPU อีกครั้งที่ไม่ถูกบังคับให้ใช้งานฟังก์ชั่นอย่างเช่นsin()ทำให้ชีวิตของผู้ใช้ภาษาของคุณง่ายขึ้นสำหรับไมโครคอนโทรลเลอร์นั้น

  • แม้แต่ไลบรารีมาตรฐานหลักก็ไม่มีค่าเมื่อคุณกำลังเขียนโปรแกรมเคอร์เนล คุณไม่สามารถใช้งานได้write()หากไม่มี syscall ในเคอร์เนลและคุณไม่สามารถนำไปใช้printf()โดยไม่write()ได้ ในฐานะที่เป็นโปรแกรมเมอร์เคอร์เนลเป็นหน้าที่ของคุณในการจัดหาwrite()syscall คุณไม่สามารถคาดหวังให้มันอยู่ที่นั่นได้

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

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


16

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

โมดูลย่อยนี้ให้ประโยชน์มากมายกับคุณ:

  • ช่วยลดปริมาณงานที่ต้องใช้เมื่อสนับสนุนแพลตฟอร์มฮาร์ดแวร์ใหม่เนื่องจากรหัสห้องสมุดมาตรฐานส่วนใหญ่สามารถใช้งานได้ไม่เชื่อเรื่องฮาร์ดแวร์
  • การปรับใช้ไลบรารีมาตรฐานสามารถปรับให้เหมาะสมได้หลายวิธี (สำหรับความเร็ว, พื้นที่, สำหรับการใช้ทรัพยากร ฯลฯ ) ระบบคอมพิวเตอร์ในยุคต้น ๆ จำนวนมากมีคอมไพเลอร์เพียงตัวเดียวเท่านั้นและการมีไลบรารี่มาตรฐานแยกต่างหากหมายความว่านักพัฒนาสามารถสลับการใช้งานเพื่อให้เหมาะกับความต้องการของพวกเขา
  • ฟังก์ชั่นห้องสมุดมาตรฐานไม่จำเป็นต้องมีอยู่ เมื่อเขียนโค้ด C โลหะเปลือยคุณมีคอมไพเลอร์เต็มรูปแบบ แต่ฟังก์ชั่นห้องสมุดมาตรฐานส่วนใหญ่ไม่ได้อยู่ที่นั่นและบางอย่างเช่นไฟล์ I / O ไม่สามารถทำได้ หากคอมไพเลอร์จำเป็นต้องใช้ฟังก์ชั่นนี้แสดงว่าคุณไม่สามารถมีคอมไพเลอร์ C ตามมาตรฐานในบางแพลตฟอร์มที่คุณต้องการมากที่สุด
  • ในระบบแรก ๆ คอมไพเลอร์ได้รับการพัฒนาโดย บริษัท ที่ออกแบบฮาร์ดแวร์ ไลบรารีมาตรฐานมักถูกจัดเตรียมโดยผู้จำหน่ายระบบปฏิบัติการเนื่องจากพวกเขามักต้องการการเข้าถึงฟังก์ชันการทำงาน (เช่นการเรียกระบบ) เฉพาะสำหรับแพลตฟอร์มซอฟต์แวร์นั้น มันเป็นไปไม่ได้ที่ผู้เขียนคอมไพเลอร์จะต้องสนับสนุนชุดค่าผสมของฮาร์ดแวร์และซอฟต์แวร์ที่แตกต่างกันทั้งหมด (เคยมีความหลากหลายมากขึ้นทั้งในสถาปัตยกรรมฮาร์ดแวร์และแพลตฟอร์มซอฟต์แวร์)
  • ในภาษาระดับสูงไลบรารีมาตรฐานสามารถนำไปใช้เป็นไลบรารีที่โหลดแบบไดนามิก การใช้งานไลบรารีมาตรฐานเดียวสามารถใช้โดยคอมไพเลอร์หลายตัวและ / หรือภาษาการเขียนโปรแกรม

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


6

คำตอบที่เป็นมุมเพิ่มเติม: การจัดการทรัพย์สินทางปัญญา

ตัวอย่างที่น่าสังเกตคือการใช้ Math.Pow (double, double) ใน. NET Frameworkซึ่ง Microsoft ซื้อจาก Intel และยังคงไม่เปิดเผยแม้ว่าเฟรมเวิร์กไปเป็นโอเพ่นซอร์ส (เพื่อความถูกต้องในกรณีข้างต้นเป็นการเรียกภายในแทนที่จะเป็นไลบรารี แต่ความคิดมีอยู่) ไลบรารีที่แยกจากภาษานั้นเอง (ในทางทฤษฎีแล้วยังเป็นส่วนย่อยของไลบรารีมาตรฐาน) สามารถให้ความช่วยเหลือด้านภาษาในการวาด เส้นแบ่งระหว่างสิ่งที่ต้องรักษาความโปร่งใสและสิ่งที่ยังไม่เปิดเผย (เนื่องจากสัญญาของพวกเขากับบุคคลที่สามหรือเหตุผลอื่น ๆ ที่เกี่ยวข้องกับ IP)


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

@LightnessRacesinOrbit - อืมฉันยังคงเห็นอยู่ที่นั่น (เมื่อค้นหา "intel") คุณสามารถค้นหาการอ้างอิงถึงซอร์สโค้ดล่าสุด (ในความคิดเห็นล่าสุด) และการนำไปใช้ทางเลือกอื่น (ในคำตอบที่สอง) ซึ่งเป็นแบบสาธารณะ แต่มีความซับซ้อนและความไร้ประสิทธิภาพแสดงความคิดเห็นซึ่งให้คำใบ้ว่าทำไม การใช้งานอย่างมีประสิทธิภาพอย่างแท้จริงอาจต้องการความรู้เชิงลึกเกี่ยวกับรายละเอียดมากมายเกี่ยวกับระดับ CPU ซึ่งไม่จำเป็นต้องมีในโดเมนสาธารณะ
miroxlav

5

บักและการดีบัก

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

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


5

นี่เป็นคำถามที่ยอดเยี่ยม!

รัฐแห่งศิลปะ

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

กระนั้นการใช้งาน C ++ ทั้งหมดที่ฉันรู้จะมีจำนวนอินทิลินซ์น้อยที่สุดเท่าที่เป็นไปได้ที่คอมไพเลอร์ให้มา

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

ทำไม?

ลองพิจารณาแนวคิดในการย้ายการทำงานบางส่วนจากไลบรารีมาตรฐานไปยังคอมไพเลอร์

ข้อดี:

  • การวินิจฉัยที่ดีกว่า: อินทรินสามารถเป็นกรณีพิเศษได้
  • ประสิทธิภาพที่ดีขึ้น: อินทรินสามารถเป็นกรณีพิเศษได้

ข้อเสีย:

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

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


5

ในฐานะนักออกแบบภาษาฉันต้องการที่จะสะท้อนคำตอบอื่น ๆ ที่นี่ แต่ให้ผ่านสายตาของคนที่กำลังสร้างภาษา

API ยังไม่เสร็จสิ้นเมื่อคุณเพิ่มทุกอย่างที่คุณสามารถทำได้ API จะเสร็จสิ้นเมื่อคุณทำทุกอย่างเสร็จแล้ว

ต้องระบุภาษาการเขียนโปรแกรมโดยใช้บางภาษา คุณต้องสามารถถ่ายทอดความหมายเบื้องหลังโปรแกรมใด ๆ ที่เขียนด้วยภาษาของคุณ ภาษานี้ยากมากในการเขียนและยากที่จะเขียนได้ดี โดยทั่วไปแล้วมันมีแนวโน้มที่จะเป็นภาษาอังกฤษที่แม่นยำและมีโครงสร้างที่ดีในการสื่อความหมายไม่ใช่กับคอมพิวเตอร์ แต่สำหรับนักพัฒนาคนอื่น ๆ โดยเฉพาะผู้พัฒนาที่เขียนคอมไพเลอร์หรือล่ามสำหรับภาษาของคุณ นี่คือตัวอย่างจากสเป็ค C ++ 11, [intro.multithread / 14]:

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

Blek! ใครก็ตามที่ทำความเข้าใจว่า C ++ 11 จัดการมัลติเธรดสามารถเข้าใจได้อย่างไรว่าทำไมถ้อยคำจึงต้องมีความทึบแสง แต่นั่นก็ไม่ได้ให้อภัยความจริงที่ว่ามันคือ ... เอ่อ ... ทึบเลย!

ตรงกันข้ามกับคำจำกัดความของstd::shared_ptr<T>::resetในส่วนไลบรารีของมาตรฐาน:

template <class Y> void reset(Y* p);

ผลกระทบ:เทียบเท่ากับshared_ptr(p).swap(*this)

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

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

และเราเห็นเส้นที่พร่ามัวอย่างแน่นอน:

  • ใน Java java.lang.ref.Reference<T>อาจเพียง แต่จะ subclassed โดยเรียนห้องสมุดมาตรฐานjava.lang.ref.WeakReference<T> java.lang.ref.SoftReference<T>และjava.lang.ref.PhantomReference<T>เพราะพฤติกรรมของReferenceจึงโอบลึกกับสเปคภาษา Java ว่าพวกเขาต้องการที่จะนำข้อ จำกัด บางอย่างเข้าไปในส่วนหนึ่งของกระบวนการที่นำมาใช้เป็น "ห้องสมุดมาตรฐาน" ชั้นเรียน
  • ใน C # มีคลาส System.Delegate ซึ่งสรุปแนวคิดของผู้รับมอบสิทธิ์ แม้จะมีชื่อมันก็ไม่ได้เป็นตัวแทน นอกจากนี้ยังเป็นคลาสนามธรรม (ไม่สามารถสร้างอินสแตนซ์) ที่คุณไม่สามารถสร้างคลาสที่ได้รับจาก มีเพียงระบบเท่านั้นที่สามารถทำได้ผ่านคุณสมบัติที่เขียนไว้ในข้อกำหนดภาษา

2

สิ่งนี้มีความหมายเพิ่มเติมจากคำตอบที่มีอยู่ (และยาวเกินไปสำหรับความคิดเห็น)

มีเหตุผลอย่างน้อยสองประการสำหรับไลบรารีมาตรฐาน:

Barrier to Entry

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

คุณกำลังตัดตัวเองออกจากผู้มีส่วนร่วมจำนวนมากหากคุณไปเส้นทางนั้น

โหลดรหัสร้อน

หลายภาษามีคุณสมบัตินี้ในระดับหนึ่งหรืออีกระดับหนึ่ง แต่มันจะซับซ้อนอย่างมากในการโหลดรหัสที่กำลังทำการโหลดร้อนอีกครั้ง หาก SL แยกจากรันไทม์สามารถโหลดใหม่ได้


3
"คอมไพเลอร์ที่เคารพตนเองควรเป็นโฮสต์ของตัวเอง" - ไม่ใช่เลย มันจะไม่มีจุดหมายที่จะมีเวอร์ชั่นของ LLVM ที่เขียนใน C, C ++, Objective-C, Swift, Fortran และอื่น ๆ เพื่อรวบรวมภาษาเหล่านี้ทั้งหมด
gnasher729

@ gnasher729 ไม่ได้เป็นกรณีพิเศษ (พร้อมกับเป้าหมายหลายภาษาอื่น ๆ เช่น CLR)?
Jared Smith

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

2

นี่เป็นคำถามที่น่าสนใจ แต่มีคำตอบที่ดีอยู่แล้วหลายข้อดังนั้นฉันจะไม่ลองตอบคำถามทั้งหมด

อย่างไรก็ตามสองสิ่งที่ฉันคิดว่าไม่ได้รับความสนใจพอ:

ครั้งแรกคือสิ่งที่ทั้งไม่ชัดเจนตัดสุด มันเป็นคลื่นความถี่นิดหน่อยเพราะมีเหตุผลที่จะทำสิ่งต่าง ๆ ตัวอย่างคอมไพเลอร์มักรู้เกี่ยวกับไลบรารีมาตรฐานและฟังก์ชั่นของมัน ตัวอย่างของตัวอย่าง: ฟังก์ชัน "Hello World" ของ C - printf - เป็นสิ่งที่ดีที่สุดที่ฉันนึกได้ มันเป็นฟังก์ชั่นห้องสมุดมันต้องเรียงตามเพราะมันขึ้นอยู่กับแพลตฟอร์ม แต่คอมไพเลอร์จะต้องทราบพฤติกรรม (การนำไปใช้งาน) เพื่อเตือนโปรแกรมเมอร์เกี่ยวกับการเรียกใช้ที่ไม่ถูกต้อง สิ่งนี้ไม่ได้เป็นระเบียบ แต่ถูกมองว่าเป็นการประนีประนอมที่ดี อนึ่งนี่คือคำตอบที่แท้จริงของคำถาม "ทำไมการออกแบบนี้" ส่วนใหญ่: ประนีประนอมจำนวนมากและ "ดูเหมือนจะเป็นความคิดที่ดีในเวลานั้น" ไม่เสมอ "นี่เป็นวิธีที่ชัดเจนในการทำ" หรือ "

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

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

ตัวอย่างเช่น:

  • คุณไม่สามารถเป็นคอมไพเลอร์ที่เข้ากันได้

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

นอกจากนี้ยังมีปัญหาที่คล้ายกันหากคุณต้องการปรับแต่งหรือขยายฟังก์ชั่น 'ห้องสมุด' นี่เป็นเรื่องธรรมดามากกว่าที่คุณคิด เพียงแค่ติดกับเธรด: หน้าต่าง, ลินุกซ์และหน่วยประมวลผลเครือข่ายที่แปลกใหม่ทั้งหมดต่างก็ทำเกลียวค่อนข้างแตกต่างกัน ในขณะที่บิต linux / windows อาจค่อนข้างคงที่และสามารถใช้ API ที่เหมือนกันสิ่งของ NPU จะเปลี่ยนตามวันของสัปดาห์และ API ด้วย คอมไพเลอร์จะเบี่ยงเบนอย่างรวดเร็วเมื่อผู้คนตัดสินใจว่าบิตใดที่พวกเขาต้องการเพื่อสนับสนุน / สามารถทำได้โดยไม่ต้องออกไปอย่างรวดเร็วหากไม่มีวิธีที่จะแยกสิ่งเหล่านี้ออก

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