2 คะแนน โดย GN⁺ 2025-12-14 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ผู้เขียนแก้ปริศนา 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 ความคิดเห็น

 
GN⁺ 2025-12-14
ความคิดเห็นจาก Hacker News
  • Gleam เป็นภาษาที่ สวยงาม จริง ๆ อยากให้ Elixir พัฒนาไปในทิศทางนี้ในแง่ของระบบ type
    Gleam ก็ทำงานบน BEAM ซึ่งเป็น Erlang VM เช่นกัน ทำให้จัดการ concurrency และคิวได้ง่ายมาก
    ecosystem ก็ดีมาก เพียงแต่กังวลว่าหลังยุค LLM การพัฒนาภาษาใหม่ ๆ หลังปี 2021 ดูเหมือนจะหยุดชะงัก
    ถึงอย่างนั้น Gleam ก็เข้ามาได้ถูกจังหวะก่อนประตูจะปิด และคาดว่าอีกไม่นาน LLM ก็น่าจะตามทัน

    • อยากรู้ว่าทำไมถึงคิดว่า LLM ทำให้การพัฒนาภาษาหยุดชะงัก โมเดลรุ่นใหม่มีความรู้ถึงปีนี้แล้ว และยังเรียนรู้ภาษาใหม่ได้ค่อนข้างดีถ้ามีตัวอย่างไม่กี่แบบ
      ภาษาแต่ละภาษาก็คงไม่ต่างกันสุดขั้วทั้งด้านไวยากรณ์และปรัชญาอยู่แล้ว เลยคิดว่าไม่น่าจะเป็นปัญหาใหญ่
    • การบอกว่า Gleam ถูกสร้างบน OTP นั้นไม่ค่อยถูกต้อง Erlang VM คือ BEAM ส่วน OTP คือชุดของ ไลบรารีและหลักการออกแบบ ของ Erlang
      Gleam มี subset ของ OTP ที่ปลอดภัยด้าน type เป็นของตัวเอง ดูไลบรารีที่เกี่ยวข้องได้ที่ gleam-lang/otp
    • ใช่แล้ว Erlang VM คือ BEAM ไม่ใช่ OTP และ implementation ของ OTP ใน Gleam ก็ยังไม่สมบูรณ์เท่า Elixir หรือ Erlang
    • ผมเองก็เพิ่งทำโปรเจ็กต์แรกด้วย Elixir ที่มีฟีเจอร์ LLM อยู่ด้วย และกลับรู้สึกว่ากระแสนี้อาจ ช่วยเร่งการยอมรับภาษา ก็ได้
    • Elixir เองก็กำลังค่อย ๆ นำ set-theoretic typing เข้ามาเช่นกัน เอกสารที่เกี่ยวข้อง: gradual-set-theoretic-types
  • ปีนี้ผมลองทำ Advent of Code ด้วย Gleam แล้วค่อนข้างประทับใจ
    ข้อดีคือประสิทธิภาพดี และ language server ก็ทรงพลังจนน่าทึ่ง ทั้ง auto formatting, auto import, การช่วยเติม pattern matching ทำให้ประสบการณ์พัฒนาดีมาก
    ข้อเสียคือ formatter ชอบยืดโค้ดในแนวตั้งมากเกินไป และเพราะเน้นความเรียบง่ายจึงมีการพิมพ์ซ้ำอย่าง list.map เยอะ อีกทั้ง ecosystem ของไลบรารียังไม่มากพอ

    • ผมก็แปลกใจกับประสิทธิภาพเหมือนกัน ไม่ถึงระดับ C แต่เร็วกว่าที่คิดมาก language server ก็ทำงานได้ดีแทบทุก IDE
      list.map ย่อได้ด้วย import gleam/list.{range, map} แบบนี้ การพอร์ตไลบรารี C ก็ดูน่าสนใจเหมือนกัน
    • ข้อเสียพวกนั้นพอรับได้ แต่ที่ลำบากคือไม่มี if/else หรือ guard ทำให้การแตกแขนงแบบ boolean ยืดยาวเกินไป
    • ผมทำ AoC ด้วย F# ก็ให้ความรู้สึกคล้ายกัน การต้องเขียน namespace ซ้ำ ๆ อย่าง List.map ทำให้ การค้นพบสิ่งที่มีอยู่ (discoverability) แย่ลง
    • การจัด format ของ argument น่าจะเป็นเพราะ อัลกอริทึมของ Prettier แต่ถึงอย่างนั้นผมก็ยังคิดว่าดีกว่า binpacking ของ clang-format มาก
  • ผมชอบ Gleam แต่เสียดายเรื่อง ข้อจำกัดของการเรียกฟังก์ชัน recursive ทำให้เรียกฟังก์ชันภายในได้ไม่อิสระนัก
    ในแง่ไวยากรณ์มันสง่างามน้อยกว่า Scheme และในแง่แนวคิดก็เรียบง่ายกว่า Erlang แต่ static typing ก็ยังเป็นข้อดี
    ผมเคยใช้ OCaml ด้วย แต่มีปัญหาเรื่อง lock file ของ opam ทำให้ reproducibility ของ environment ไม่ดี เลยรู้สึกว่าอยากให้ ecosystem ของ SML ใหญ่กว่านี้

    • ผมก็คิดคล้ายกัน Haskell ดูยอดเยี่ยมในเชิงทฤษฎี แต่แค่ hello world ง่าย ๆ ก็ ใช้ทรัพยากร มากแล้ว
      Idris 2 มีทั้ง dependent types และการออกแบบที่สง่างาม แต่ ecosystem เล็ก ส่วน PureScript ใช้งานจริงได้มากกว่า Haskell แต่ก็ผูกกับ runtime ของ JS
    • ถ้าชอบสาย ML ขอแนะนำ ReScript v12 อยู่กึ่งกลางได้สมดุลดีระหว่าง OCaml กับ Gleam
  • พอเห็นฟีเจอร์ 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 ตัวใหม่ก็ได้

    • ในฐานะนักพัฒนาแบ็กเอนด์ ผมเคยรู้สึกว่า Elm น่าสนใจ แต่ก็ถอยห่างเพราะ ความขัดแย้งกับผู้สร้าง และการหยุดออกรุ่น ถึงอย่างนั้นสถาปัตยกรรมของมันก็ยังมีประโยชน์กับโปรเจ็กต์อื่น
    • ผมเองก็เพิ่งลองทำแอปเล็ก ๆ ด้วย Gleam + Lustre เมื่อไม่นานมานี้ และมันออกมาดีกว่า Elm + PostgREST มาก ตอนนี้เลยตั้งใจจะใช้กับโปรเจ็กต์ใหญ่ขึ้นต่อไป
    • ผมลองดู Lustre แล้วแต่ ecosystem ยังเล็ก และยังไม่มีตัวอย่างเรื่อง authentication เลยเลือกไปทาง LiveView แทน ถึงอย่างนั้น ergonomics ก็ดีมาก หวังว่าจะเติบโตต่อ
  • ช่วงนี้ในยุค LLM ก็เริ่มสงสัยว่าการเรียนภาษาใหม่ยังคุ้มอยู่ไหม
    ถ้าเป็นภาษาที่ LLM ไม่ได้เรียนมา ก็กลัวว่า ประโยชน์ในฐานะเครื่องมือ จะลดลง

    • ในระยะยาว ถ้า LLM เรียนรู้ภาษาใหม่ไม่ได้ ก็แปลว่ามันล้มเหลวในเป้าหมายของการเป็น ปัญญาทั่วไป
    • เมื่อ 1-2 ปีก่อนความกังวลแบบนั้นมีอยู่จริง แต่ตอนนี้ Claude Code ก็เขียนโค้ด Elixir ได้ค่อนข้างดีแล้ว ข้อมูลฝึกน้อยก็ไม่ใช่ปัญหา
    • Claude จัดการกับ Gleam ได้ดีเหมือนกัน เพราะทั้งเอกสารและ คุณภาพของข้อความวินิจฉัย ดี ทำให้ LLM เรียนรู้ง่าย ให้ข้อความวินิจฉัยได้ระดับเดียวกับ Rust
      ตรงกันข้าม Swift มีไวยากรณ์ซับซ้อนกว่า จึงยากสำหรับ LLM
    • ถ้ามองภาษาเป็นเครื่องมือ ความต้องการของตลาดที่ต่ำ อาจเป็นข้อจำกัดที่ใหญ่กว่า
    • หวังว่าภาษาใหม่ ๆ จะไม่หยุดเกิดขึ้นเพราะข้อจำกัดของ LLM
  • ตอนเคยดู Gleam เมื่อก่อน ผมรู้สึกว่าไม่มี dynamic dispatch (interface หรือ type class) เลยไม่แน่ใจว่าตอนนี้เป็นยังไงบ้าง

    • ปกติก็แก้ด้วยการ “ส่ง struct ของฟังก์ชันเข้ามา” แนวทางแบบ explicit นี้กลับดีตรงที่ไม่ต้องแบกความซับซ้อนของ generics
    • Gleam รองรับ first-class functions ดังนั้นจึงทำ dynamic dispatch ได้ type class หรือ interface สุดท้ายก็แก้ได้ด้วย higher-order functions
  • [first, ..rest] หรือ [first, second] ใช้ได้ แต่ [first, ..middle, last] ใช้ไม่ได้
    น่าจะเป็นการตั้งใจห้ามไว้เพราะ มีค่าใช้จ่ายสูง

  • โชคดีที่ ตำรวจชื่อบทความในบล็อก มาถึงที่เกิดเหตุอย่างรวดเร็ว
    ลิงก์ที่เกี่ยวข้อง