- ผู้เขียนแก้ปริศนา 12 วันของ Advent of Code 2025 ด้วย Gleam และประทับใจเป็นพิเศษกับ ข้อความแจ้งข้อผิดพลาดระดับเดียวกับ Rust และ สไตล์ฟังก์ชันนัลที่เน้นพายป์ไลน์
- ฟังก์ชันในตัวอย่าง
echo, fold_until, list.transpose ช่วยให้การดีบักและการแก้ปัญหาเชิงประกอบง่ายขึ้น และ ความปลอดภัยบนพื้นฐานของ option type ก็มีประโยชน์ในการจัดการปริศนาแบบกริด
- จุดที่ถูกมองว่าไม่สะดวกเมื่อใช้งานซ้ำ ๆ ได้แก่ การที่ standard library ไม่มี file IO และ regex, ข้อจำกัดของ list pattern matching, และ ไวยากรณ์การเปรียบเทียบที่ต้องเขียนแบบชัดเจน
- เนื่องจากมี ความต่างในการจัดการจำนวนเต็ม ระหว่างเป้าหมาย Erlang VM กับ JavaScript จึงต้องใช้
bigi และในบางปริศนาก็แก้ปัญหาด้วยการเรียกใช้ เครื่องมือภายนอก (glpsol)
- โดยรวมแล้ว ผู้เขียนมองว่า การเปลี่ยนมาคิดแบบฟังก์ชันนัลทำให้การแก้ปริศนาชัดเจนขึ้น และแสดงความคาดหวังว่าอยากลองนำ Gleam ไปใช้กับโปรเจกต์จริง เช่น การพัฒนาเว็บเซิร์ฟเวอร์
Advent of Code 2025 และการเลือก Gleam
- ผู้เขียนซึ่งทำ Advent of Code ครบทุกปี ได้เลือกใช้ ภาษา Gleam ในปีนี้เพื่อแก้ปริศนาเป็นเวลา 12 วัน
- งานปีนี้ถูกย่อจาก 25 วันเหลือ 12 วัน และแม้แต่ละข้อจะยากขึ้น แต่ก็มีโครงสร้างที่เหมาะกับการเรียนรู้
- ด้วยความที่ปริศนาดำเนินไปอย่างรวดเร็วและต้องเจอโจทย์ซับซ้อนก่อนจะมีชุดเครื่องมือพร้อมครบ จึงกลายเป็น สภาพแวดล้อมที่เหมาะอย่างยิ่งสำหรับการเรียนรู้ภาษาใหม่
จุดเด่นของภาษา Gleam
- มีจุดเด่นคือ ไวยากรณ์กระชับ, ข้อความข้อผิดพลาดจากคอมไพเลอร์ที่มีประโยชน์, และ ฟีดแบ็กที่เป็นมิตรระดับ Rust
- สไตล์ฟังก์ชันนัลที่ขับเคลื่อนด้วย pipe operator เข้ากันได้ดีกับโครงสร้างโจทย์ AoC (parse → transform → fold)
- ส่วนขยาย Gleam สำหรับ IntelliJ และ LSP ทำงานได้เสถียร ทำให้สภาพแวดล้อมการพัฒนาน่าใช้งาน
- การเขียนโปรแกรมเชิงฟังก์ชัน (FP) ช่วยเปลี่ยนวิธีคิดจากโค้ดเชิงคำสั่ง ไปสู่การ อธิบายแก่นของปัญหา
ฟีเจอร์สำคัญและตัวอย่างการใช้โค้ด
echo : ฟังก์ชันพิมพ์ออกอย่างง่ายที่ใช้ดูค่าระหว่างทางในพายป์ไลน์ จึงดีบักได้โดยไม่ต้องจัดรูปแบบสตริง
- อย่างไรก็ตาม มีการกล่าวถึงว่าเพราะไม่มี string interpolation จึงทำให้การสร้างข้อความต้องใช้ตัวดำเนินการ
<>" บ่อย ซึ่งไม่สะดวกนัก
- option type (
dict.get) : ใช้สำรวจเพื่อนบ้านในปริศนาแบบกริดได้อย่างปลอดภัยโดยไม่ต้องตรวจขอบเขตแยก
- ยูทิลิตีสำหรับ list
list.transpose: ทำให้การทรานสโพสเมทริกซ์ช่วยลดความซับซ้อนของโครงสร้างปริศนา
list.combination_pairs: เมื่อสร้างคู่ของจุด 3D ก็เขียนได้ในบรรทัดเดียวโดยไม่ต้องใช้ลูปซ้อน
fold_until: ฟังก์ชัน fold ที่หยุดก่อนกำหนดได้เมื่อเข้าเงื่อนไข จึงมีประสิทธิภาพกับการคำนวณซ้ำในปริศนา
ข้อจำกัดและจุดไม่สะดวกของ Gleam
- standard library ไม่มี file IO, จึงใช้แพ็กเกจ
simplifile แทน
- ความสามารถด้าน regex ก็ต้องพึ่งพาภายนอกผ่าน
gleam_regexp
- ข้อจำกัดของ list pattern matching: ไม่รองรับรูปแบบ
[first, ..middle, last]
- การจัดการการเปรียบเทียบแบบชัดเจน: ต้องใช้ชนิด
order ทำให้ไวยากรณ์ยืดยาวเมื่อเทียบแบบง่าย ๆ
การประยุกต์ใช้ขั้นสูงและตัวอย่างในแต่ละปริศนา
bigi : ใช้เพื่อป้องกัน integer overflow เมื่อคอมไพล์ไปยังเป้าหมาย JavaScript
- XOR bitmask: ใน Day 10-1 โมเดลปัญหาการสลับไฟถูกออกแบบด้วยการดำเนินการ XOR ทำให้แก้ได้อย่างมีประสิทธิภาพ
- การเรียก
glpsol: ใน Day 10-2 สร้างไฟล์ LP แล้วรันคำสั่งภายนอกเพื่อแก้สมการเชิงเส้น
- memoization key: ใน Day 11-2 ใช้โหนดและสถานะร่วมกันเป็นคีย์ ทำให้คำนวณเสร็จได้ทันที
- ปริศนาข้อสุดท้าย อาศัยสมมติฐานเกี่ยวกับอินพุต และแก้ด้วยการเปรียบเทียบพื้นที่อย่างง่าย (
heuristic_area <= max_area)
บทสรุปและแผนต่อไป
- Gleam แสดงให้เห็นถึง จุดแข็งด้านความปลอดภัยและพลังในการแสดงออก แม้จะมีข้อจำกัดของ standard library
- พายป์ไลน์, option/result type, ฟังก์ชัน list,
fold_until ล้วนช่วยให้การแก้ปริศนาชัดเจนขึ้น
- ผู้เขียนมีแผนจะนำไปใช้กับ โปรเจกต์จริงอย่างการพัฒนาเว็บเซิร์ฟเวอร์ ในอนาคต และตั้งใจจะใช้ Gleam ต่อใน Advent of Code ปีถัดไป
- ซอร์สโค้ดทั้งหมดเปิดเผยอยู่ใน GitHub repository (
tymscar/Advent-Of-Code/2025/gleam/aoc/src)
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
Gleam เป็นภาษาที่ สวยงาม จริง ๆ อยากให้ Elixir พัฒนาไปในทิศทางนี้ในแง่ของระบบ type
Gleam ก็ทำงานบน BEAM ซึ่งเป็น Erlang VM เช่นกัน ทำให้จัดการ concurrency และคิวได้ง่ายมาก
ecosystem ก็ดีมาก เพียงแต่กังวลว่าหลังยุค LLM การพัฒนาภาษาใหม่ ๆ หลังปี 2021 ดูเหมือนจะหยุดชะงัก
ถึงอย่างนั้น Gleam ก็เข้ามาได้ถูกจังหวะก่อนประตูจะปิด และคาดว่าอีกไม่นาน LLM ก็น่าจะตามทัน
ภาษาแต่ละภาษาก็คงไม่ต่างกันสุดขั้วทั้งด้านไวยากรณ์และปรัชญาอยู่แล้ว เลยคิดว่าไม่น่าจะเป็นปัญหาใหญ่
Gleam มี subset ของ OTP ที่ปลอดภัยด้าน type เป็นของตัวเอง ดูไลบรารีที่เกี่ยวข้องได้ที่ gleam-lang/otp
ปีนี้ผมลองทำ Advent of Code ด้วย Gleam แล้วค่อนข้างประทับใจ
ข้อดีคือประสิทธิภาพดี และ language server ก็ทรงพลังจนน่าทึ่ง ทั้ง auto formatting, auto import, การช่วยเติม pattern matching ทำให้ประสบการณ์พัฒนาดีมาก
ข้อเสียคือ formatter ชอบยืดโค้ดในแนวตั้งมากเกินไป และเพราะเน้นความเรียบง่ายจึงมีการพิมพ์ซ้ำอย่าง
list.mapเยอะ อีกทั้ง ecosystem ของไลบรารียังไม่มากพอlist.mapย่อได้ด้วยimport gleam/list.{range, map}แบบนี้ การพอร์ตไลบรารี C ก็ดูน่าสนใจเหมือนกันList.mapทำให้ การค้นพบสิ่งที่มีอยู่ (discoverability) แย่ลงผมชอบ Gleam แต่เสียดายเรื่อง ข้อจำกัดของการเรียกฟังก์ชัน recursive ทำให้เรียกฟังก์ชันภายในได้ไม่อิสระนัก
ในแง่ไวยากรณ์มันสง่างามน้อยกว่า Scheme และในแง่แนวคิดก็เรียบง่ายกว่า Erlang แต่ static typing ก็ยังเป็นข้อดี
ผมเคยใช้ OCaml ด้วย แต่มีปัญหาเรื่อง lock file ของ opam ทำให้ reproducibility ของ environment ไม่ดี เลยรู้สึกว่าอยากให้ ecosystem ของ SML ใหญ่กว่านี้
Idris 2 มีทั้ง dependent types และการออกแบบที่สง่างาม แต่ ecosystem เล็ก ส่วน PureScript ใช้งานจริงได้มากกว่า Haskell แต่ก็ผูกกับ runtime ของ JS
พอเห็นฟีเจอร์
echoแล้วก็รู้สึกว่าอยากให้ debugger มี ความสามารถดูผลลัพธ์ระหว่างทาง แบบนี้เป็นพื้นฐานถ้าดูผลลัพธ์ระหว่าง slice ของ array หรือกลาง chain ของ filter ได้โดยไม่ต้องแก้โค้ดก็คงดีมาก
อีกอย่าง ผมคิดว่าการใช้ array 2 มิติเป็นกริดนั้นไม่มีประสิทธิภาพนัก array 1 มิติ + ข้อมูลขอบเขต จะปลอดภัยและมีประสิทธิภาพกว่า
ผมไม่ได้รู้จัก Gleam มากนัก แต่
list.map(fn(line) { line |> calculate_instruction })ดูเหมือนว่าน่าจะเขียนเป็น
list.map(calculate_instruction)ได้เลยไม่ใช่เหรอGleam เป็นภาษาที่ยอดเยี่ยม แม้มันจะไม่ค่อยโดนใจผมมากนัก แต่ก็ยินดีที่เห็นคนอื่นสนุกกับมัน
ผมคิดว่าคู่ผสม Gleam + Lustre อาจกลายเป็น Elm ตัวใหม่ก็ได้
ช่วงนี้ในยุค LLM ก็เริ่มสงสัยว่าการเรียนภาษาใหม่ยังคุ้มอยู่ไหม
ถ้าเป็นภาษาที่ LLM ไม่ได้เรียนมา ก็กลัวว่า ประโยชน์ในฐานะเครื่องมือ จะลดลง
ตรงกันข้าม Swift มีไวยากรณ์ซับซ้อนกว่า จึงยากสำหรับ LLM
ตอนเคยดู Gleam เมื่อก่อน ผมรู้สึกว่าไม่มี dynamic dispatch (interface หรือ type class) เลยไม่แน่ใจว่าตอนนี้เป็นยังไงบ้าง
[first, ..rest]หรือ[first, second]ใช้ได้ แต่[first, ..middle, last]ใช้ไม่ได้น่าจะเป็นการตั้งใจห้ามไว้เพราะ มีค่าใช้จ่ายสูง
โชคดีที่ ตำรวจชื่อบทความในบล็อก มาถึงที่เกิดเหตุอย่างรวดเร็ว
ลิงก์ที่เกี่ยวข้อง