Skip article metadata to content Skip navigation

On Fuzziness of Terminology: Compiling vs Interpreting

Cover image: Bird at Santa Barbara Fisherman's Wharf

เมื่อเราต้องทำงานกับภาษาโปรแกรม ( ⁠programming language ⁠) ภาษาต่าง ๆ มากกว่า 1 ภาษา เรามักจะพบว่าแต่ละภาษามีลักษณะที่แตกต่างกันออกไปเสมือนว่าแต่ละภาษาก็มีโลกเป็นของตัวเอง  หนึ่งในความแตกต่างทั้งหลายที่เห็นได้ชัดเจนที่สุดก็คือ ลักษณะของภาษาที่จะทำงานแบบ compile หรือว่าแบบ interpret?

ก่อนที่เราจะลงรายละเอียดเกี่ยวกับเรื่องนี้กัน ลองมาตอบคำถามต่อไปนี้ในใจก่อนครับ

คำถาม

ภาษาโปรแกรมต่อไปนี้ เป็นภาษาที่ทำงานแบบ compile หรือว่าแบบ interpret?

  • C / C++
  • Java
  • Python
  • JavaScript / TypeScript
  • Ruby
  • Golang
  • Rust
  • OCaml / ReasonML

( ⁠ไม่ได้กล่าวถึงภาษาโปรดของใครก็ขออภัยนะครับ 5 5 5 + ⁠)

เรามาค่อย ๆ ไขปริศนากับคำถามเหล่านี้ไปพร้อม ๆ กันทีละสเต็ปกันครับ

บทสนทนา 1: นิยามที่พบได้ทั่วไป

นิยามของคำว่า compile กับ interpret ในมุมมองของคนทั่วไปมักมีลักษณะดังนี้

นิยามในมุมมองคนทั่วไป
compile

คือการที่เราต้องแปลงโค้ดจากที่เขียนไว้ ให้กลายเป็น executable file หรือ byte code ที่เราสามารถนำมารันต่อได้ภายหลัง

เช่น การแปลงโค้ดภาษา C จากไฟล์ *.c ให้สุดท้ายกลายเป็นไฟล์ binaryในกรณีนี้หมายรวมถึงทุกขั้นตอนในสายพานของการแปลงโค้ด ได้แก่ compile, assemble, link และ load ที่เราสามารถ execute ได้โดยตรง

อีกตัวอย่างหนึ่งคือการ compile จาก Java source code ให้กลายเป็น Java bytecode ซึ่งจะถูกนำไปรันต่อด้วย Java virtual machine ( ⁠JVM ⁠)

interpret

คือการที่เรามีตัวแปลภาษาที่รันคำสั่งแต่ละขั้นตอนตามลำดับได้ทันที โดยไม่จำเป็นต้องมีการแปลงไฟล์ก่อน

เช่น การที่เรารันคำสั่ง JavaScript ได้จาก JavaScript console หรือเรารันคำสั่ง Python ได้จาก interactive shell หรือแม้แต่ Jupyter

แต่ว่านิยามข้างต้นมีข้อโต้แย้งจากตัวอย่างดังต่อไปนี้

  1. ภาษา JavaScript สมัยใหม่ ( ⁠เช่น EMCAScript 2015 เป็นต้นไป ⁠) สามารถรันได้โดยตรงโดยผ่าน NodeJS เวอร์ชันที่รองรับก็ได้ ( ⁠ทำงานแบบ interpret ตามนิยามข้างต้น ⁠)

    หรืออาจจะใช้ tool เพื่อช่วยแปลงโค้ดจาก EMCAScript เวอร์ชันใหม่ ๆ ไปยังเวอร์ชันที่เก่ากว่าที่สามารถรันภายใน browser ได้ ( ⁠ซึ่งเรียกว่า source-to-source compilation ⁠)  เช่น BabelJS เป็นต้น

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

บทสนทนา 2: ตัวอย่างภาษา Python

ข้อโต้แย้ง

อ้าว ก็นี่ไง! เวลาเราเปิด Python interactive shell เช่น การรันคำสั่ง python ขึ้นมาโดยตรง หรืออาจจะเป็นการใช้งาน IPython/Jupyter ก็ได้ ทั้งหมดนี้รวม ๆ เรียกว่า REPL ( ⁠read–eval–print–loop ⁠) ขึ้นมา ก็เห็นชัด ๆ ว่ามันเป็น interpreter ที่รันคำสั่งภาษา Python ได้โดยตรงเลย  ไม่เห็นจะต้องแปลงโค้ด Python เป็นอย่างอื่นก่อนเลยแล้วจึงจะรันได้

ประเด็นอยู่ที่ว่า การที่โปรแกรมเมอร์ผู้ใช้งานไม่เห็นโค้ดถูก compile ด้วยตาตัวเอง ก็ไม่ได้หมายความว่าตัวโค้ด Python จะไม่เกิดการ compile เสียหน่อย  ในความเป็นจริงแล้วนั้น Python ที่ใช้กันทั่วไป ในกรณีนี้หมายถึง CPython implementation ของภาษา Python จะมีขั้นตอนหนึ่งที่แปลงโค้ดจาก Python source code ให้กลายเป็น Python bytecode ก่อน  แล้วจากนั้นจึงมี Python runtime ตัวหนึ่ง ที่คอยรันคำสั่งของ Python bytecode เหล่านั้นอีกทอดหนึ่ง

ข้อโต้แย้ง

ก็ถูกแล้วนี่! สุดท้ายเราในฐานะโปรแกรมเมอร์ผู้ใช้งานก็รันโค้ด Python ได้โดยตรง ไม่ต้อง compile เอง เป็นไปตามนิยามที่ว่ามาข้างต้นเลย

ในความเป็นจริง เราสามารถสร้าง bytecode จาก source code ของ Python เพื่อนำไปรันภายหลังได้ ( ⁠ไม่ต่างกับภาษา Java ⁠)  แต่ interactive shell ของ Python ทำหน้าที่อำนวยความสะดวก ( ⁠compile + execute ⁠) ให้กับโปรแกรมเมอร์เฉย ๆ ซึ่งกระบวนการดังกล่าวไม่มีส่วนเกี่ยวข้องใด ๆ กับสเปกของภาษา Python เอง

ข้อโต้แย้ง

แต่สุดท้ายก็ต้องใช้ Python runtime เพื่อรันโค้ด python ทีละคำสั่งอยู่ดีนี่? ก็ต้องพูดได้สิว่า Python เป็นภาษาที่ทำงานแบบ interpret  ⁠…

แต่เดี๋ยวก่อนนะ! ถ้าแบบนี้เราก็ต้องจัดให้ Java เป็นภาษาแบบ interpret ด้วยเหมือนกันสิเนี่ยะ มันเกิดอะไรขึ้นเนี่ยะ?

ใช่แล้ว นั่นก็เพราะนิยามของคำว่า compile และ interpret ข้างต้นยังไม่รัดกุมพอ  เราจะมาลองให้นิยามของคำทั้ง 2 คำที่แม่นยำมากขึ้นกันในสเต็ปถัดไปกัน


นิยามของคำว่า compile และ interpret

ต่อไปนี้เป็นนิยามที่ถูกต้องของคำว่า compile และ interpret

compile

คือการแปลงของโค้ดชุดหนึ่งไปยังโค้ดอีกชุดหนึ่ง ซึ่งอาจจะเปลี่ยนจากภาษาโปรแกรมภาษาหนึ่งไปยังอีกภาษาหนึ่งก็ได้ หรือภาษาปลายทางจะยังคงเป็นภาษาเดิมก็ต่อ  แต่ประเด็นสำคัญคือโครงสร้างของโค้ด ( ⁠syntax tree ⁠) ต้องเกิดการเปลี่ยนแปลงขึ้น จึงจะนับว่าเป็นการ compile ฉะนั้นแล้ว code formatter อาจจะจัดว่าเป็นการ compile หรือไม่ก็ได้ ขึ้นกับกรณี

ยกตัวอย่างเช่น การแปลงโค้ดภาษา C ให้กลายเป็น assembly code หรือ machine code  หรือการแปลง Java source code ให้กลายเป็น Java bytecode  หรือการแปลง EMCAScript 2015 + ให้กลายเป็น browser-compatible JavaScriptโดยใช้ BabelJS เป็นต้น และยังมีกรณีอื่น ๆ อีกมากมาย

interpret

คือการใช้ virtual machine ( ⁠VM ⁠) เพื่อรันโค้ดบางอย่างบนเลเยอร์เหนือ machine ที่อยู่ระดับต่ำกว่า  เช่น การใช้ Python runtimeruntime นี้ถือว่าเป็น virtual machine อย่างหนึ่ง ในการรัน Python bytecode

หมายเหตุ: หากเรากลับมาพิจารณาบทสนทนาแรกสุดอีกครั้งนึง จะพบว่า  สิ่งที่แยกภาษา C และภาษา Java ( ⁠ที่เชื่อว่าทำงานแบบ “compile” ⁠) ออกจากภาษา Python ( ⁠ที่เชื่อว่าทำงานแบบ “interpret” ⁠) แท้จริงแล้วก็คือเวลาที่โค้ดของโปรแกรมเหล่านั้นถูก compile และ execute ต่างหาก  กล่าวคือ

  • สำหรับภาษา C นั้น  เรานิยม compile โค้ดให้กลายเป็น executable binary ก่อน  แล้วหลังจากนั้นจึงมีการ execute โค้ดดังกล่าว ซึ่งอาจเกิดขึ้นเมื่อใดก็ได้ และกี่ครั้งก็ได้
  • ภาษา Java ก็เช่นกัน  สำหรับการนำโค้ด Java ไปใช้งาน เรามัก compile จาก Java source code ให้กลายเป็น bytecode ก่อน แล้วจึงนำ bytecode นี้ไปใช้งานจริงกับ JVM ภายหลัง
  • ในกรณีของภาษา Python นั้น  เรานิยมนำ Python source file ต้นฉบับ เอาไปใช้งานจริงโดยตรง  ซึ่งโค้ดดังกล่าวจะถูก compile ให้กลายเป็น bytecode ทันที  ตอนที่โปรแกรมกำลังจะถูก execute ด้วย Python runtime เท่านั้น ในบางกรณี อาจมีการแคช bytecode ที่ถูกสร้างขึ้นนี้ในรูปของไฟล์ *.pyc อีกด้วย

บทสนทนา 3: สวมหมวกนักปฏิบัตินิยม

ข้อโต้แย้ง

เนี่ยะ เวลาโปรแกรมเมอร์ใช้คำว่า compile กับ interpret เนี่ยะ เรากำลังพูดถึงว่า เราต้องเอาโค้ดไป compile ก่อนใช้งานหรือเปล่า หรือว่าเราเอาโค้ดนี้ไป interpret กันหน้างานเลย  ⁠…

จากมุมมองนี้ แล้วมันผิดตรงไหนที่เราจะบอกว่า Java เป็นภาษาแบบ compile และ Python เป็นภาษาแบบ interpret?

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

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

  • ตัวอย่างที่ชัดเจนที่สุดก็คือโค้ดที่เขียนตามมาตรฐานใหม่ของ JavaScript จำพวก EMCAScript 2015 + เป็นต้น ซึ่งเราอาจจะนำมารันโดยตรงด้วย NodeJS เลยก็ได้  หรืออาจจะใช้ BabelJS เพื่อ compile ให้กลายเป็น JavaScript เวอร์ชันที่สามารถรันภายใน browser ก็ได้เช่นกัน
  • อีกตัวอย่างหนึ่งคือภาษา OCaml และรวมถึงภาษา ReasonML ที่เป็นพี่น้องด้วย ซึ่งมีหลาย option ให้เลือกดังต่อไปนี้
    1. สามารถ compile โค้ดให้เป็น bytecode แล้วจึงรันด้วย runtime ก็ได้
    2. หรือจะ compile ให้เป็น machine code ก็ได้
    3. ไม่เพียงแค่นั้น ปัจจุบันมี OCaml implementation ชื่อว่า BuckleScript ที่สามารถ compile โค้ด OCaml ให้รันบน JavaScript ได้อีกด้วย

คลายปม

เพื่อคลายข้อสงสัย ขอเฉลย ณ ตรงนี้ว่า  คำว่า compile และ interpret แท้จริงแล้วไม่ได้เอาไว้อธิบายตัวภาษาโปรแกรมโดยตรง แต่เอาไว้อธิบาย implementation หนึ่ง ๆ ของภาษาโปรแกรมต่างหาก  ไม่ใช่เรื่องแปลกที่ภาษาโปรแกรมภาษาเดียวกัน  จะมี implementation ที่หลากหลายแตกต่างกันออกไป

ข้อสังเกตอย่างหนึ่งที่ผู้เขียนพบคือ เวลาโปรแกรมเมอร์พูดถึงภาษาโปรแกรมภาษาหนึ่ง เราอาจกำลังหมายถึง ecosystem ของภาษานั้น ๆ เสียมากกว่า ( ⁠เช่น เวลาพูดถึง Python อาจจะหมายถึง CPython implementation ที่เป็นที่นิยม ซึ่งพูดรวมไปถึง Python language, Python bytecode, Python runtime เป็นต้น ⁠) ดูเพิ่มเติม metonymy จึงเป็นเหตุให้เราใช้คำว่า compile หรือ interpret อย่างที่พบในปัจจุบัน

บทแทรก: จนถึงตรงนี้ ผู้เขียนใช้คำว่า Python bytecode ในบทความหลายครั้ง  ในความเป็นจริงแล้ว Python bytecode ที่พูดถึงนี้ เป็นเพียง implementation detail ของ CPython ecosystem เท่านั้น ไม่ถือว่าเป็นส่วนหนึ่งของ Python ภาษาหลักแต่อย่างใด implementation อื่นของ Python อย่างเช่น PyPy ก็มี bytecode ของตัวเองเช่นกัน  แต่ว่าเป็นคนละตัวกับของ CPython

บทสนทนา 4: static type checking

อีกปัจจัยหนึ่งที่ผู้คนมักนำมาเชื่อมโยงกับการจำแนกภาษาที่ทำงานแบบ compile หรือ interpret ก็คือ static type checking

ข้อโต้แย้ง

อย่างที่รู้กันอยู่แล้วว่า ภาษาที่มีการ compile อย่างภาษา C หรือ Java จะมีการตรวจสอบ type ของค่าต่าง ๆ ภายในโปรแกรมระหว่างโปรแกรมกำลัง compile

แล้วทำไมภาษา Python ถึงทำไม่ได้? ทั้ง ๆ ที่มีการ compile ด้วยเหมือนกัน  หรือว่านิยามใหม่ของคำว่า compile ที่เสนอมาจะใช้ไม่ได้แล้วล่ะมั้ง  ⁠…

นี่ขนาดภาษา JavaScript ยังต้องมีการ extend syntax กลายเป็นภาษาใหม่อย่าง TypeScript แน่นอนว่า TypeScript ไม่ใช่ JavaScript เพราะเป็น superset ของ JavaScript  นั่นหมายความว่าโค้ดบางอย่างใน TypeScript ไม่ใช่ valid JavaScript เพื่อแก้ปัญหาเรื่อง static type check เลย

แม้ว่า static type checking จะมีความเกี่ยวข้องกับ code compilation  แต่ก็ไม่จำเป็นที่ทั้งสองอย่างนี้จะต้องมาคู่กันเสมอไป

ก่อนอื่น อย่างที่ทราบกันดีว่า static type checking ที่เกิดขึ้นระหว่างที่โปรแกรมกำลัง compile นั้น จะช่วยทำให้เรามั่นใจได้ว่า การรันโปรแกรมที่ compile แล้ว จะไม่เกิด error อันเกิดจาก type ที่ผิดพลาดได้อีก  และจึงไม่จำเป็นที่โปรแกรมต้องตรวจสอบความถูกต้องของ type ระหว่างที่รันโปรแกรมอีก และอาจเกิดการทำ type erasure ได้ด้วย

แต่ว่าอันที่จริงแล้ว implementation ของภาษาหนึ่ง ๆ ก็สามารถเลือกที่จะโยกย้าย type checking จากตอน compilation time ไปยังตอน execution time ของโปรแกรมได้ยกเว้นบางกรณี นั่นหมายความว่า compiler ไม่จำเป็นว่าจะต้องมี type checking ในทุกกรณีเสมอไป สังเกตว่าในบางกรณีของ JavaScript to JavaScript compiler อย่าง BabelJS ก็ไม่มีการตรวจสอบ type เช่นกัน ก็ถือว่าเป็น compiler

หมายเหตุ: ในปัจจุบัน Python 3.5 + รองรับการกำหนด type ให้แก่ค่าต่าง ๆ ในโค้ดได้ ( ⁠เรียกว่า type annotation ⁠) อ่านรายละเอียดของ type annotation ได้ ซึ่งโปรแกรมเมอร์ผู้ใช้งานสามารถเลือกที่จะ annotate type ให้แก่ค่าบางค่าในโค้ด หรือจะทั้งหมดของโค้ดก็ได้ ตอนนี้มีเครื่องมืออย่าง mypy ที่สามารถใช้ข้อมูล type annotation เพื่อช่วยเหลือโปรแกรมเมอร์ผู้ใช้งานในการตรวจสอบความถูกต้องของ type ในโปรแกรมได้ แต่ CPython implementation จะไม่นำข้อมูลเกี่ยวกับ type เหล่านี้มาช่วยทำ type checking ตอนรันโปรแกรมแต่อย่างใด แต่ type checking ตอน execution time แบบเดิมยังเกิดขึ้นตามปกติ ในอนาคตอาจจะมี implementation ของ python ตัวใหม่ที่จะอนุญาตให้โค้ด compile ผ่าน ก็ต่อเมื่อโปรแกรมผ่านการตรวจสอบ type เท่านั้น ก็เป็นได้

บทสนทนา 5: ของแบบนี้เค้าดูกันตอนจบเกม

ข้อโต้แย้ง

ถึงแม้จะพยายามบอกว่าคำว่า compile กับ interpret เอาไว้ใช้อธิบาย implementation ของภาษาก็ตามที  แต่เอาจริง ๆ ไหม? ทำไมเราไม่ดูล่ะว่าภาษานั้น ๆ สามารถแปลงให้กลายเป็น machine code ได้เลย หรือว่าจำเป็นต้องมี virtual machine มารันโปรแกรมนั้น ไม่ทางใดก็ทางหนึ่ง

พูดง่าย ๆ คือเราตัดสินกันนี่แหละว่าภาษาทำงานแบบ compile หรือ interpret โดยดูจากว่า โค้ดจะถูกรันโดย physical machine โดยตรง หรือว่าจะถูกรันด้วย virtual machine กันแน่

ประเด็นนี้สามารถโต้แย้งได้ง่ายมาก โดยดูจากตัวอย่างค้านจากภาษา OCaml/ReasonML ที่ได้กล่าวถึงไปแล้วก่อนหน้านี้

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

แท้ที่จริงแล้ว code ของโปรแกรมไม่ว่าอยู่ในรูปแบบหรือภาษาใด ๆ ก็ย่อมต้องการ machine ในการรันทั้งสิ้น  สังเกตว่า physical machine นั้นทำหน้าที่ไม่ได้แตกต่างจาก virtual machine เลย ( ⁠ซึ่งก็คือการรันโค้ดเหมือน ๆ กัน ⁠)เราอาจเรียกว่า code และ machine เป็นของที่คู่กันก็ว่าได้

ฉะนั้นในบริบทนี้  virtual machine และ physical machine เห็นจะแตกต่างกันแต่เพียงระดับชั้นนามธรรม ( ⁠layers of abstraction ⁠) ก็เท่านั้นเอง

บทแทรก: สมมติว่าเรามีโปรแกรมอันหนึ่ง ที่มีส่วนประกอบดังต่อไปนี้

  • โค้ด CC ที่เขียนด้วยภาษา X0X_0
  • runtime R0R_0 สำหรับภาษา X0X_0 ที่เขียนด้วยภาษา X1X_1
  • runtime R1R_1 สำหรับภาษา X1X_1 ที่เขียนด้วยภาษา X2X_2
  • \ldots
  • runtime Rn1R_{n-1} สำหรับภาษา Xn1X_{n-1} ที่เขียนด้วยภาษา XnX_n
  • และ runtime RnR_n สำหรับภาษา XnX_n ที่เขียนด้วย machine language

เราจะสามารถพูดได้ว่าการนำโค้ด C:=C+R0+R1++RnC^* := C+R_0+R_1+\ldots+R_n ทั้งหมดมารวมกัน จะถือว่า CC^* เป็นโค้ดที่เขียนด้วย machine language โดยตรงก็ได้  เพราะว่าในมุมมองของ machine การรันโค้ด CC^* นั้นไม่แตกต่างจากการรันโค้ดที่เขียนด้วย machine language โดยตรงนั่นเอง


ทิ้งท้าย

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

เพื่อขยายความตรงประเด็นนี้ มาดูกันว่าเรา compile หรือ interpret โค้ดกันไปทำไม

  • เรา compile โค้ดไปเพื่อ
    1. ทำให้โค้ดสามารถนำไปรันใน platform ต่าง ๆ ได้
    2. ช่วย optimize โค้ดให้โปรแกรมทำงานได้อย่างมีประสิทธิภาพมากขึ้น
    3. ช่วยตรวจสอบความถูกต้องโปรแกรมในรูปแบบต่าง ๆ เช่น type checking เป็นต้น
  • เรา interpret โค้ดไปเพื่อ  ⁠… เอ่อ  ⁠… ก็รันโปรแกรมไง

เมื่อพิจารณา implementation ของภาษาโปรแกรมภาษาหนึ่ง ๆ เราจะพบว่า อาจมีบางขั้นตอนเป็นการ compile และบางขั้นตอนเป็นการ interpret ก็ได้  ยิ่งไปกว่านั้น บาง implementation ก็มีลักษณะเป็นลูกผสมที่มีขั้นตอนการ compile ผสมกับการ interpret โค้ด เช่น just-in-time ( ⁠JIT ⁠) compiler เป็นต้น

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

Side Story

คำเตือน

เนื้อหาส่วนนี้อาจล้าสมัย แต่บันทึกไว้เป็นวัตถุทางประวัติศาสตร์

ในช่วงหลายเดือนที่ผ่านมา ผู้เขียนได้เว้นว่างจากการเขียน blog ไป เนื่องจากพบว่าเครื่องมือในการสร้างเว็บไซต์เดิม ไม่ตอบโจทย์ความต้องการ ( ⁠ที่เรื่องมากสุด ๆ ⁠) ของผู้เขียน  จึงได้มีความพยายามที่จะย้ายสำมโนครัวจาก GatsbyJS มายัง Pelican ในโลก Python  สิ่งที่ได้มีการปรับปรุง ประกอบได้ด้วย

  1. การแทรก sidenoteก็ข้อความแบบนี้นี่แหละ
  2. การระบายสีพื้นหลังของโค้ดบางบรรทัด เพื่อเน้นส่วนสำคัญ
  3. การเพิ่ม diff view เพื่อแสดงการเปลี่ยนแปลงของโค้ดจากเวอร์ชันหนึ่งสู่เวอร์ชันถัดไปแบบ incremental ( ⁠สามารถดูตัวอย่างได้จากบทความที่แล้ว ⁠)
  4. ผู้เขียนได้สร้าง text pre-processor ขึ้นมาตัวหนึ่ง เพื่อทำให้การเขียนบทความมีความยืดหยุ่นสูงขึ้น ตอนนี้โปรเจคนี่ยังอยู่ในระยะตั้งไข่ รอจนโปรเจคนี้เติบโตเต็มวัยแล้วจะมาเขียนถึงในอนาคต  ตอนนี้อ่านรายละเอียดได้ที่หน้า GitHub ของโปรเจค Paxter ยกตัวอย่างเช่น ผู้เขียนสามารถประกาศค่าและฟังก์ชันต่าง ๆ ด้วยภาษา Python และใช้งานภายในบทความเดียวกันได้เลย ดังนี้
sample.paxter
@!##{
def emph(text):
return f"<em>{text}</em>"
name = "John"
age = 21
= '&hairsp;ๆ'
}##
My name is @name and @emph{I was @{age - 1} years old last year}.
ไม่ต้องเถียงกันว่าไม้ยมกต้องมีเว้นวรรคข้างหน้า 1 เคาะหรือไม่
ในเมื่อเราเลือกปรับขนาดของเว้นวรรคได้สบาย@

ซึ่งจะให้ผลลัพธ์เป็น

sample.html
My name is John and <em>I was 20 years old last year</em>.
ไม่ต้องเถียงกันว่าไม้ยมกต้องมีเว้นวรรคข้างหน้า 1 เคาะหรือไม่
ในเมื่อเราเลือกปรับขนาดของเว้นวรรคได้สบาย&hairsp;

โปรดอ่านรายละเอียดเพิ่มเติมเกี่ยวกับเว็บไซต์นี้ได้ท้ายหน้า about

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

ป.ล. นี่อย่าให้เริ่มพูดถึงคำว่า functional, imperative, declarative, object-oriented, yadda– yadda– yadda– อะไรพวกนี้อีกนะ