ทำไมเราต้องแลกเปลี่ยนนามธรรมเพื่อความรวดเร็ว


11

ทำไมภาษาระดับสูงถึงไม่สามารถเข้าถึงภาษาระดับต่ำกว่าในแง่ของความเร็วได้? ตัวอย่างภาษาระดับสูง ได้แก่ Python, Haskell และ Java ภาษาระดับต่ำจะยากกว่าที่จะนิยาม แต่สมมติว่า C. การเปรียบเทียบสามารถพบได้ทั่วอินเทอร์เน็ต1และพวกเขาทั้งหมดเห็นด้วยว่า C นั้นเร็วกว่ามากบางครั้งอาจเป็น 10 หรือมากกว่า1

อะไรที่ทำให้ประสิทธิภาพแตกต่างกันมากและทำไมภาษาระดับสูงถึงไม่ทัน

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


ตัวอย่าง:1


5
"และพวกเขาก็เห็นพ้องกันว่า C นั้นเร็วกว่ามาก" - นั่นมันผิดอย่างแน่นอน
Raphael

2
อย่างไรก็ตามผมคิดว่าการโพสต์เป็นคำตอบที่ดีที่สุดโดยคำตอบของฉันเป็นคำถามในทำนองเดียวกันป่วยรู้สึก ; ซ้ำ?
Raphael

2
ดูเพิ่มเติมที่นี่และที่นี่ ระวังคำตอบขยะ
Raphael

ที่เกี่ยวข้อง: stackoverflow.com/questions/6964392/…ตำนานของ "ภาษาระดับสูง" ทั้งหมดที่เกิดขึ้นช้านั้นค่อนข้างเศร้า
xji

ฉันเห็นด้วยกับคนอื่น ๆ ที่เป็นนามธรรม! = ความเชื่องช้า แต่ฉันกลัวว่าจะมีปัญหาใหญ่กว่าที่ครูวิทยาศาสตร์คอมพิวเตอร์ (ฉันเป็นคนหนึ่ง) ไม่รู้ตัว นั่นคือสำหรับโปรแกรมจริง (1,000 บรรทัดของโค้ดขึ้นไป) มีหลายวิธีที่จะทำและสิ่งเหล่านั้นอาจแตกต่างกันในประสิทธิภาพการทำงานตามลำดับความสำคัญ แค่คิดเกี่ยวกับ big-O โดยสิ้นเชิงพลาดจุด ตรวจสอบที่นี่
Mike Dunlavey

คำตอบ:


19

debunking บางตำนาน

  1. ไม่มีสิ่งดังกล่าวในฐานะที่เป็นอย่างรวดเร็ว ภาษาทั่วไปสามารถสร้างรหัสที่รวดเร็ว แต่ภาษาต่าง ๆ จะเก่งกว่าเกณฑ์มาตรฐานที่แตกต่างกัน เราสามารถจัดอันดับภาษาในชุดมาตรฐานที่มีข้อบกพร่องโดยเฉพาะ แต่ไม่สามารถจัดอันดับภาษาในสุญญากาศได้

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

  3. บางครั้งมันไม่ปลอดภัยไม่เป็นนามธรรมทำให้ C เร็ว การขาดขอบเขตอาเรย์และตัวชี้โมฆะตรวจสอบช่วยประหยัดเวลาและเป็นสาเหตุของช่องโหว่ด้านความปลอดภัยจำนวนมากตลอดหลายปีที่ผ่านมา

  4. ภาษาไม่รวดเร็วการใช้งานนั้นรวดเร็ว ภาษาที่เป็นนามธรรมจำนวนมากเริ่มช้าเนื่องจากความเร็วไม่ใช่เป้าหมายของพวกเขา แต่เร็วขึ้นเมื่อมีการเพิ่มประสิทธิภาพมากขึ้น

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

ความเรียบง่าย, ความเร็ว, สิ่งที่เป็นนามธรรม: เลือกสองอย่าง

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

ในภาษาที่เป็นนามธรรมสูงที่เรียบง่ายเช่น Python หรือ JavaScript เนื่องจากเราไม่ทราบเกี่ยวกับการแสดงข้อมูลจนกว่ารันไทม์มีการอ้างอิงตัวชี้จำนวนมากและการตรวจสอบแบบไดนามิกเกิดขึ้นที่รันไทม์ซึ่งช้า

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

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

บทคัดย่อไม่ได้หมายความว่าช้า

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

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


2
"รหัส C มีแนวโน้มที่จะเร็วขึ้นเพราะคนที่ต้องการประสิทธิภาพทุก ๆ นิ้วใช้ C" - อย่างแน่นอน ฉันต้องการดูเกณฑ์มาตรฐานของรูปแบบ "เวลาทำงานโดยเฉลี่ยของโค้ดที่เขียนโดยนักศึกษา / ผู้เชี่ยวชาญ X-year ที่มีประสบการณ์ Y ปีใน Z" ฉันคาดหวังว่าคำตอบสำหรับ C มักจะเป็น "รหัสไม่ถูกต้อง" สำหรับ X และ Y ขนาดเล็กมันน่าสนใจมากที่จะเห็นว่าคุณต้องใช้ประสบการณ์ / ความเชี่ยวชาญมากเพียงใดในการเพิ่มศักยภาพในการปฏิบัติตามสัญญา C
Raphael

แฮสเค็ลล์เป็นข้อยกเว้นที่พิสูจน์กฎได้จริง ๆ ;) ฉันคิดว่า C ++ พบจุดกึ่งกลางที่สมเหตุสมผลเกี่ยวกับ GC โดยพอยน์เตอร์อัจฉริยะของมันตราบใดที่คุณไม่ซ้อนพอยน์เตอร์พอยน์เตอร์และจะเร็วเท่า C.
Kaveh

0

นี่คือแนวคิดสำคัญบางประการเกี่ยวกับเรื่องนี้

  • เปรียบเทียบง่าย / กรณีศึกษาเพื่อให้ wrt abstraction vs speed คือ java vs c ++ java ได้รับการออกแบบมาให้ย่อบางส่วนของ c ++ เช่นการจัดการหน่วยความจำ ในวันแรก (ประมาณการประดิษฐ์ภาษากลางปี ​​1990), การตรวจจับขยะ java ไม่เร็วมาก แต่หลังจากไม่กี่ทศวรรษของการวิจัยนักสะสมขยะจะถูกปรับอย่างมาก / เร็ว / ปรับให้เหมาะสมดังนั้นนักสะสมขยะจึงถูกกำจัดเป็นส่วนใหญ่ ประสิทธิภาพท่อระบายน้ำบน java เช่นดูหัวข้อข่าวปี 1998 นี้: การทดสอบประสิทธิภาพแสดง Java เร็วเท่า C ++ / javaworld

  • ภาษาการเขียนโปรแกรมและวิวัฒนาการที่ยาวนานของพวกมันนั้นมี "โครงสร้างแบบพีระมิด / ลำดับชั้น" โดยธรรมชาติซึ่งเป็นรูปแบบการออกแบบของตัวพิมพ์ดีด ที่ด้านบนของพีระมิดเป็นสิ่งที่ควบคุมส่วนล่างของพีระมิด กล่าวอีกนัยหนึ่งการสร้างบล็อกทำจากการสร้างบล็อก สิ่งนี้สามารถเห็นได้ในโครงสร้าง API ด้วย ในแง่นี้สิ่งที่เป็นนามธรรมมากขึ้นจะนำไปสู่ส่วนประกอบใหม่ที่ด้านบนของปิรามิดที่ควบคุมส่วนประกอบอื่น ๆ ดังนั้นในความรู้สึกมันไม่มากจนทุกภาษาอยู่ในระดับซึ่งกันและกัน แต่ภาษานั้นเรียกใช้งานประจำในภาษาอื่น ๆ เช่นภาษาสคริปต์จำนวนมาก (python / ruby) มักจะเรียกไลบรารี C หรือ C ++, รูทีนตัวเลขหรือเมทริกซ์เป็นตัวอย่างทั่วไปของสิ่งนี้ ดังนั้นจึงมีภาษาระดับสูงและระดับต่ำกว่าและภาษาระดับสูงเรียกภาษาระดับต่ำกว่าเพื่อพูด ในแง่นี้การวัดความเร็วสัมพัทธ์ไม่ได้เปรียบจริง ๆ

  • อาจกล่าวได้ว่ามีการคิดค้นภาษาใหม่ตลอดเวลาเพื่อพยายามเพิ่มประสิทธิภาพการแลกเปลี่ยนที่เป็นนามธรรม / กล่าวคือเป้าหมายการออกแบบที่สำคัญ อาจจะไม่มากนักที่สิ่งที่เป็นนามธรรมจะยิ่งเสียสละความเร็ว แต่ความสมดุลที่ดีกว่านั้นมักจะถูกแสวงหาด้วยการออกแบบที่ใหม่กว่า เช่น Google Go มีหลายวิธีที่ได้รับการปรับให้เหมาะสมโดยเฉพาะกับการแลกเปลี่ยนในใจเพื่อให้พร้อมกันทั้งในระดับสูงและนักแสดง ดูเช่นGoogle Go: เพราะเหตุใดภาษาการเขียนโปรแกรมของ Google จึงสามารถเทียบเคียงJava ได้ใน enterprise / techworld


0

วิธีที่ฉันชอบคิดเกี่ยวกับประสิทธิภาพคือ "ที่ซึ่งยางเข้ากับถนน" คอมพิวเตอร์ดำเนินการคำสั่งไม่ใช่แบบนามธรรม

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

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

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


0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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