39 คะแนน โดย xguru 2022-12-12 | 7 ความคิดเห็น | แชร์ทาง WhatsApp

"Little Language" คืออะไร?

  • "ภาษาเล็ก" คือภาษาที่ถูกสร้างขึ้นโดยมีเป้าหมายเพื่อแก้ปัญหาเฉพาะด้าน
    → SQL, RegEx, Dhall,..
    → และยังถูกเรียกว่า DSL ด้วย

ทำไมภาษาเล็กจึงจำเป็น?

  • เมื่อแอปพลิเคชันซับซ้อนขึ้นมาก ซอร์สโค้ดก็ใหญ่ขึ้น แต่ก็ยิ่งทำความเข้าใจได้ยากขึ้นด้วย
  • การ onboarding พนักงานใหม่ทำได้ยาก เกิดข้อผิดพลาดจากการไม่เข้าใจ dependencies และการเปลี่ยนแปลงโค้ดก็ยิ่งจัดการได้ยากขึ้นเรื่อยๆ
  • ในช่วง 10 ปีที่ผ่านมา codebase มีขนาดใหญ่ขึ้น 100~500 เท่า
    • Linux kernel เริ่มต้นในปี 1992 ด้วย 10,000 บรรทัด แต่ผ่านไป 20 ปีกลายเป็น 30 ล้านบรรทัด
  • โค้ดเหล่านี้ไม่ได้เกิดขึ้นเพียงเพราะ "มีฟีเจอร์มากขึ้น" เท่านั้น แต่เพราะวิธีที่เราสร้างซอฟต์แวร์ได้เปลี่ยนไป
    • ซอฟต์แวร์ก็เหมือนการสร้างพีระมิด เพื่อวางหินก้อนสุดท้าย เราต้องมีหินอีกจำนวนมากรองรับอยู่ด้านล่าง

เอาชนะเทรนด์นี้

  • การสร้าง OS สมัยใหม่จำเป็นต้องใช้โค้ดหลายล้านบรรทัดจริงหรือ?
  • Alan Kay ท้าทายสมมติฐานนี้ในโครงการ STEPS ปี 2006
  • เราคิดว่าการสร้าง "ภาษา" ที่เหมาะกับปัญหาที่ต้องแก้ จะทำให้การแก้ปัญหาง่ายขึ้น และทำให้โซลูชันเล็กลงพร้อมทั้งเข้าใจได้ง่ายขึ้น

  • ใน STEPS มีการสร้างภาษาชื่อ Nile และทำให้ Cairo renderer ที่มี 44,000 บรรทัด สามารถทำงานใกล้เคียงกันได้ด้วยโค้ดราว 300 บรรทัด

แล้วทำไมภาษาแบบระดับสูงถึงไม่พอ?

  • แค่สร้างภาษาทั่วไปที่มีระดับสูงขึ้นอีกไม่ได้หรือ?
  • ส่วนตัวผมคิดว่าเราไปถึงจุดที่ผลตอบแทนลดลง (diminishing returns) ของพลังในการแสดงออกของภาษาทั่วไปแล้ว
  • ถ้าจะเป็นภาษาที่สูงกว่านี้ หน้าตาจะเป็นอย่างไร? ถ้ายก Python เป็นตัวอย่าง มันก็มีระดับสูงมากจนดูเหมือน pseudo code อยู่แล้ว
  • ปัญหาของภาษาทั่วไปคือ คุณต้องแปลปัญหาของคุณเป็นอัลกอริทึมก่อน แล้วจึงค่อยแสดงอัลกอริทึมนั้นด้วยภาษาเป้าหมาย
    • ในหนังสือ Programming Pearls ของ Jon Bentley ปี 1986 เคยเชิญ Donald Knuth และ Doug McIlroy ที่มีชื่อเสียง มาลองเขียนโปรแกรมนับความถี่ของคำ โดย Don เขียนด้วย WEB ซึ่งเป็นภาษาดัดแปลงจาก Pascal ใช้โครงสร้างข้อมูลซับซ้อนยาวถึง 10 หน้า
    • ส่วน Doug ทำด้วยไวยากรณ์ Unix pipe เพียง 6 บรรทัด โดยใช้ tr, sort, uniq, sort, sed เป็นต้น

ยิ่งน้อยยิ่งดี Less is More

  • คำสั่ง Unix ข้างต้นแสดงให้เห็นลักษณะอีกอย่างของภาษาเล็ก
    "ภาษาที่ทรงพลังน้อยกว่า แต่มี runtime ที่ทรงพลังมากกว่า"
  • Gonzalez พูดถึงเทรนด์นี้ไว้ใน "The end of history for programming"
    • คือผลักปัญหาใน user space ไปเป็นปัญหาของ runtime
      • ทำให้โปรแกรมมีลักษณะคล้ายการแสดงออกเชิงคณิตศาสตร์บริสุทธิ์มากขึ้น และเพิ่มความซับซ้อนของ runtime อย่างมาก
  • RegEx และ SQL ต่างก็ไม่สามารถแสดงอะไรได้นอกเหนือจากการค้นหาข้อความและงานฐานข้อมูลตามลำดับ
  • นี่แตกต่างจากภาษาอย่าง C ที่ไม่มี runtime และสามารถแสดงทุกอย่างได้
  • ภาษาเล็กยืนอยู่ที่ปลายอีกด้านหนึ่งของสเปกตรัมพลังแบบที่ C มี
    • ไม่เพียงแต่สถาปัตยกรรมคอมพิวเตอร์จะถูกทำให้เป็นนามธรรม แต่ยังจำกัดชนิดของโปรแกรมที่สามารถแสดงได้ด้วย จึงถูกออกแบบให้ Turing-incomplete
    • แม้จะฟังดูจำกัดมาก แต่กลับเปิดความเป็นไปได้อีกมิติสำหรับการ optimization และ static analysis

การวิเคราะห์แบบสแตติก

  • ภาษาที่ทรงพลังน้อยกว่านั้นให้เหตุผลกับมันได้ง่ายกว่า และสามารถให้การรับประกันที่แข็งแรงกว่าภาษาทั่วไป
  • ตัวอย่างเช่น Dhall เป็น "Total Functional Programming Language" สำหรับการสร้างไฟล์คอนฟิก
    • กล่าวคือ เพื่อขจัดความเสี่ยงของการตกอยู่ในลูปไม่สิ้นสุด โปรแกรม Dhall จึง "รับประกัน" ว่า "(1) จะไม่ crash และ (2) จะจบการทำงานภายในเวลาจำกัด"
    • ข้อ (1) ทำได้ด้วยการไม่ให้โยน exception คำสั่งที่อาจล้มเหลวจะคืนค่า Optional result (อาจมีค่าหรือไม่มีก็ได้)
    • ข้อ (2) ทำได้ด้วยการไม่อนุญาตให้มีนิยามแบบ recursive
  • ในภาษาฟังก์ชันอื่นๆ การ recursion เป็นวิธีพื้นฐานในการทำ loop แต่ Dhall ต้องพึ่งพา built-in fold function
  • การไม่มีโครงสร้าง loop ทั่วไปหมายความว่า Dhall ไม่เป็น Turing-complete แต่ก็ไม่จำเป็น เพราะมันไม่ใช่ภาษาสำหรับงานทั่วไป
  • เมื่อภาษามีขนาดเล็ก การให้เหตุผลก็ง่ายขึ้นมาก
    • เช่น การตรวจว่าโปรแกรม Python ไม่มี side effect อื่นหรือไม่นั้นทำได้ยาก แต่ใน SQL แค่ตรวจว่าคิวรีเริ่มด้วย SELECT หรือไม่ก็พอ
  • สำหรับ Nile ทีม STEPS ต้องการ graphical debugger เลยสร้างขึ้นมา และดูได้ด้วยตัวเอง
    • สิ่งนี้เป็นไปได้เพราะ Nile เป็นภาษาเล็กที่ให้เหตุผลง่าย

ความจำเป็นของความเร็ว

  • ภาษาการเขียนโปรแกรมที่ทรงพลังมากกว่า ไม่ได้แค่เพิ่มโอกาสเกิดบั๊กเท่านั้น แต่อาจส่งผลเสียต่อประสิทธิภาพด้วย
  • ตัวอย่างเช่น หากโปรแกรมไม่ได้ถูกแสดงออกมาในรูปของอัลกอริทึม runtime ก็อาจเลือกอัลกอริทึมได้เอง
    • นิพจน์ที่ช้าสามารถถูกแทนที่ด้วยสิ่งที่เร็วกว่าได้ (โดยมีเงื่อนไขว่าพิสูจน์ได้ว่าให้ผลลัพธ์เหมือนกัน)
  • ตัวอย่างเช่น SQL query ไม่ได้สั่งวิธีการ execute query
    • database engine สามารถตัดสินใจได้อย่างอิสระว่า query plan แบบใดเหมาะสม
      • จะใช้ index, composite index หรือจะ scan ตารางฐานข้อมูลทั้งหมด เป็นต้น
    • database engine สมัยใหม่ยังเก็บสถิติเกี่ยวกับการกระจายค่าของแต่ละคอลัมน์ จึงสามารถเลือก query plan ที่ดีที่สุดเชิงสถิติได้แบบทันที
    • ถ้าคิวรีมาในรูปอัลกอริทึม สิ่งเหล่านี้ก็จะทำไม่ได้
  • หนึ่งใน "secret sauce" ที่ทำให้ภาษา Nile กระชับมาก คือ "Jitblt" ซึ่งเป็น Just-in-Time compiler สำหรับ graphics rendering
    • จากการพูดคุยกันระหว่างทีม STEPS และทีม Cairo พบว่าโค้ด Cairo จำนวนมากถูกใช้ไปกับการ optimize งานผสมพิกเซลแบบทำมือ
    • ตามทฤษฎีแล้ว งานนี้เป็นสิ่งที่สามารถ offload ไปให้คอมไพเลอร์ทำได้
    • Dan Amelang จากทีม Cairo อาสามาสร้างคอมไพเลอร์แบบนี้ขึ้นมา ซึ่งก็คือ Jitblt
    • นั่นหมายความว่างาน optimization ของ graphics pipeline สามารถแยกออกจากคำอธิบายเชิงคณิตศาสตร์ล้วนๆ ว่าจะ render อะไร
      ทำให้ Nile สามารถรันได้เร็วพอๆ กับโค้ด Cairo ต้นฉบับที่ถูก optimize ด้วยมือ

Small languages, Big Potential (ภาษาเล็ก ศักยภาพใหญ่)

  • แล้วสุดท้าย STEPS เป็นอย่างไร? มันสร้าง OS ที่ทำงานได้ด้วยโค้ดที่พิมพ์ลงบนเสื้อยืดได้จริงหรือไม่?
  • ผลลัพธ์สุดท้ายของ STEPS คือ KSWorld
    • เป็น OS ที่สมบูรณ์ มีทั้งโปรแกรมแก้ไขเอกสารและโปรแกรมแก้ไขสเปรดชีตในตัว
    • มีโค้ด 17,000 บรรทัด
    • อาจจะยาวเกินกว่าจะใส่บนเสื้อยืดได้ แต่ผมคิดว่านี่คือความสำเร็จ
  • การเกิดขึ้นของ KSWorld แสดงให้เห็นว่า "ภาษาเล็ก" มีศักยภาพสูงมาก
  • แต่ก็ยังมีคำถามที่ยังตอบไม่ได้อีกมาก
    • ภาษาเหล่านี้จะคุยกันอย่างไร?
    • ควรคอมไพล์ไปเป็นตัวแทนกลางแบบเดียวกันหรือไม่?
    • หรือควรให้ runtime ที่ต่างกันอยู่ร่วมกันแบบขนาน แล้วสื่อสารกันด้วยโปรโตคอลมาตรฐาน (เช่น Unix pipe, TCP/IP)?
    • หรือแต่ละภาษาจะเล็กพอที่จะนำไป implement ใหม่บน host language หลายแบบได้?
    • หรือบางที การผสมทุกแนวทางเข้าด้วยกันอาจเป็นทิศทางที่ควรไป?
  • ไม่ว่าอย่างไร ผมเชื่อว่าเราจำเป็นต้องคิดหาวิธีอื่นในการสร้างซอฟต์แวร์
    • และบางที "ภาษาเล็ก" อาจเป็นส่วนหนึ่งของเรื่องนั้น
    • สิ่งสำคัญคือ เราไม่ควรเอาอิฐไปกองทับเพิ่มบนของเดิมไปเรื่อยๆ จนกว่าจะมีเวลามากพอที่จะคิดสิ่งที่ดีกว่าออกมาได้

7 ความคิดเห็น

 
ide127 2022-12-15

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

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

 
chicol 2022-12-14

เป็นหัวข้อที่น่าสนใจนะครับ

 
kunggom 2022-12-12

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

 
uglyduck68 2022-12-12

ว้าว ขอบคุณครับ

 
nicewook 2022-12-12

ขอบคุณที่ให้อ่านครับ

 
roxie 2022-12-12

ลิสป์ยิ้มแย้ม

 
xguru 2022-12-12

คิดว่าเป็นเรื่องที่น่าสนใจ เลยขอนำมาแบ่งปันครับ