2 điểm bởi GN⁺ 2025-12-14 | 1 bình luận | Chia sẻ qua WhatsApp
  • Tác giả đã giải các câu đố trong 12 ngày của Advent of Code 2025 bằng Gleam, và đặc biệt ấn tượng với thông báo lỗi ở mức Rust cùng phong cách hàm tập trung vào pipeline của ngôn ngữ này
  • Các hàm dựng sẵn như echo, fold_until, list.transpose giúp đơn giản hóa việc debug và giải các bài toán tổ hợp, đồng thời độ an toàn dựa trên option type hoạt động rất hữu ích khi xử lý các câu đố dạng lưới
  • Các điểm bất tiện được chỉ ra gồm thư viện chuẩn không bao gồm file IO và regex, hạn chế của pattern matching với list, cùng cú pháp so sánh tường minh gây bất tiện khi dùng lặp lại
  • Do khác biệt trong xử lý số nguyên giữa đích Erlang VM và JavaScript, cần dùng bigi; với một số câu đố, tác giả còn giải quyết bằng cách gọi công cụ ngoài (glpsol)
  • Nhìn chung, việc chuyển sang tư duy hàm đã khiến quá trình giải đố trở nên rõ ràng hơn, và tác giả bày tỏ mong muốn thử áp dụng Gleam vào dự án thực tế (ví dụ: phát triển web server)

Advent of Code 2025 và việc chọn Gleam

  • Tác giả, người đã hoàn thành Advent of Code hằng năm, năm nay chọn ngôn ngữ Gleam để giải các câu đố trong 12 ngày
    • Sự kiện năm nay được rút từ 25 ngày xuống còn 12 ngày; độ khó của từng bài cao nhưng cấu trúc lại phù hợp cho việc học
  • Tốc độ ra đề nhanh và việc gặp các bài toán phức tạp trước khi bộ công cụ kịp hoàn thiện đã tạo thành một môi trường lý tưởng để học ngôn ngữ mới

Ưu điểm của Gleam về mặt ngôn ngữ

  • Nổi bật với cú pháp gọn gàng, thông báo lỗi từ compiler hữu ích, và phản hồi thân thiện ở mức Rust
  • Phong cách hàm xoay quanh toán tử pipe rất hợp với cấu trúc bài AoC (parse → biến đổi → fold)
  • Extension Gleam cho IntelliJ và LSP hoạt động ổn định, giúp môi trường phát triển dễ chịu
  • Lập trình hàm (FP) khiến cách nghĩ chuyển từ viết mã mệnh lệnh sang mô tả bản chất của bài toán

Các tính năng chính và ví dụ dùng mã

  • echo: hàm in đơn giản cho phép kiểm tra giá trị ở giữa pipeline, giúp debug mà không cần format chuỗi
    • Việc không có nội suy chuỗi được nhắc đến như một điểm bất tiện, vì khi tạo văn bản phải dùng nhiều phép nối <>"
  • Option type (dict.get): cho phép duyệt ô lân cận trong các bài toán lưới một cách an toàn mà không cần kiểm tra biên riêng
  • Tiện ích cho list
    • list.transpose: đơn giản hóa cấu trúc bài toán nhờ phép chuyển vị ma trận
    • list.combination_pairs: tạo các cặp điểm 3D chỉ trong một dòng mà không cần vòng lặp lồng nhau
    • fold_until: hàm fold có thể dừng sớm khi đạt điều kiện, hiệu quả cho các phép tính lặp trong câu đố

Hạn chế và điểm bất tiện của Gleam

  • Thiếu file IO trong thư viện chuẩn, nên thay bằng gói simplifile
  • Tính năng regex cũng cần phụ thuộc ngoài là gleam_regexp
  • Hạn chế pattern matching với list: không hỗ trợ dạng [first, ..middle, last]
  • Xử lý so sánh tường minh: phải dùng kiểu order, khiến cú pháp trở nên dài dòng trong các so sánh đơn giản

Ứng dụng nâng cao và ví dụ theo từng câu đố

  • bigi: được dùng để tránh tràn số nguyên khi nhắm tới đích JavaScript
  • Bitmask XOR: ở Day 10-1, bài toán bật/tắt đèn được mô hình hóa bằng phép XOR để giải hiệu quả
  • Gọi glpsol: ở Day 10-2, tác giả tạo file LP rồi chạy lệnh ngoài để giải hệ phương trình tuyến tính
  • Khóa memoization: ở Day 11-2, dùng cả node và trạng thái làm khóa nên việc tính toán hoàn tất ngay lập tức
  • Câu đố cuối cùng phụ thuộc vào giả định về input và được giải bằng cách so sánh diện tích đơn giản (heuristic_area <= max_area)

Kết luận và kế hoạch sắp tới

  • Gleam cho thấy điểm mạnh về độ an toàn và khả năng biểu đạt, dù còn giới hạn ở thư viện chuẩn
  • Pipeline, option/result type, các hàm list, fold_until đã giúp việc giải đố trở nên rõ ràng hơn
  • Tác giả dự định áp dụng vào các dự án thực tế như phát triển web server, và cho biết sẽ tiếp tục dùng Gleam ở Advent of Code năm sau
  • Toàn bộ mã nguồn được công khai trong kho GitHub (tymscar/Advent-Of-Code/2025/gleam/aoc/src)

1 bình luận

 
GN⁺ 2025-12-14
Ý kiến trên Hacker News
  • Gleam thực sự là một ngôn ngữ đẹp. Tôi từng nghĩ sẽ rất hay nếu Elixir phát triển theo hướng này về mặt hệ thống kiểu
    Gleam cũng chạy trên BEAM, tức Erlang VM, nên việc xử lý đồng thời và hàng đợi trở nên rất dễ dàng
    Hệ sinh thái cũng rất tốt. Tuy vậy, tôi lo rằng kể từ sau thời kỳ LLM, sự phát triển ngôn ngữ sau năm 2021 dường như đã chững lại
    Dù vậy, Gleam đã kịp xuất hiện ngay trước khi cánh cửa đó khép lại, và tôi kỳ vọng các LLM rồi cũng sẽ bắt kịp

    • Tôi tò mò vì sao bạn nghĩ LLM làm sự phát triển ngôn ngữ chững lại. Các model mới nhất đã có kiến thức đến tận năm nay, và cũng học ngôn ngữ mới khá tốt chỉ với vài ví dụ
      Vì ngôn ngữ cũng không thể khác biệt hoàn toàn về cú pháp hay triết lý, nên có lẽ đó không phải vấn đề lớn
    • Nói Gleam được xây trên OTP là không chính xác. Erlang VM là BEAM, còn OTP là tập hợp thư viện và nguyên tắc thiết kế của Erlang
      Gleam tự cung cấp một tập con OTP an toàn kiểu riêng. Có thể xem thư viện liên quan tại gleam-lang/otp
    • Đúng vậy, Erlang VM là BEAM chứ không phải OTP. Phần triển khai OTP của Gleam chưa hoàn thiện bằng Elixir hay Erlang
    • Gần đây tôi cũng lần đầu làm một dự án Elixir có tích hợp tính năng LLM, và ngược lại lại cảm thấy xu hướng này có thể thúc đẩy việc chấp nhận ngôn ngữ
    • Elixir cũng đang dần đưa vào set-theoretic typing. Tài liệu liên quan: gradual-set-theoretic-types
  • Năm nay tôi đã giải Advent of Code bằng Gleam và thấy khá ấn tượng
    Ưu điểm là hiệu năng tốt, và language server mạnh đến mức đáng ngạc nhiên. Tự động format, tự động import, hỗ trợ pattern matching... trải nghiệm phát triển rất tuyệt
    Nhược điểm là formatter đẩy code theo chiều dọc quá nhiều, và vì đề cao sự đơn giản nên có nhiều đoạn phải lặp lại như list.map. Ngoài ra hệ sinh thái thư viện vẫn còn thiếu

    • Tôi cũng bất ngờ về hiệu năng. Không bằng C, nhưng nhanh hơn rất nhiều so với dự đoán. Language server cũng hoạt động tốt trên hầu hết IDE
      list.map có thể rút gọn bằng import gleam/list.{range, map}. Việc port các thư viện C cũng có vẻ thú vị
    • Những nhược điểm đó vẫn chấp nhận được, nhưng việc không có if/else hay guard khá bất tiện. Xử lý nhánh boolean trở nên quá dài dòng
    • Tôi làm AoC bằng F# và cảm giác cũng tương tự. Việc lặp lại namespace như List.map làm giảm khả năng khám phá (discoverability)
    • Việc format đối số có lẽ là do thuật toán Prettier. Dù vậy tôi vẫn thấy nó tốt hơn nhiều so với binpacking của clang-format
  • Tôi thích Gleam, nhưng thấy tiếc vì ràng buộc khi gọi hàm đệ quy. Không thể tự do gọi các hàm nội bộ
    Về cú pháp thì nó kém thanh thoát hơn Scheme, còn về mặt khái niệm thì đơn giản hơn Erlang. Dù vậy, kiểu tĩnh vẫn là một ưu điểm
    Tôi cũng đã dùng OCaml, nhưng vấn đề lock file của opam khiến khả năng tái tạo môi trường kém. Tôi ước gì hệ sinh thái SML lớn hơn

    • Tôi cũng nghĩ tương tự. Haskell thì hay về mặt lý thuyết, nhưng ngay cả một hello world đơn giản cũng tiêu tốn tài nguyên đáng kể
      Idris 2 có dependent types và thiết kế thanh lịch, nhưng hệ sinh thái nhỏ; còn PureScript thì thực dụng hơn Haskell nhưng lại bị ràng buộc vào runtime JS
    • Nếu thích họ ML, tôi đề xuất ReScript v12. Nó nằm ở vị trí cân bằng giữa OCaml và Gleam
  • Khi thấy tính năng echo, tôi đã nghĩ sẽ thật tuyệt nếu debugger mặc định có sẵn kiểu xem kết quả trung gian như vậy
    Sẽ rất tiện nếu có thể xem kết quả giữa chừng của slice mảng hay chuỗi filter mà không cần sửa code
    Ngoài ra tôi thấy dùng mảng 2 chiều như một grid là không hiệu quả. Mảng 1 chiều + thông tin biên sẽ an toàn và hiệu quả hơn

  • Tôi không biết nhiều về Gleam, nhưng list.map(fn(line) { line |> calculate_instruction })
    có phải có thể viết đơn giản thành list.map(calculate_instruction) không

    • Đúng vậy, tôi cũng từng xử lý gì đó phức tạp hơn rồi xóa đi và để sót lại dạng đó
    • Vâng, chính xác là vậy
  • Gleam là một ngôn ngữ tuyệt vời. Nó không thực sự hợp với tôi, nhưng thấy mọi người thích thú với nó cũng thật vui
    Tôi nghĩ tổ hợp Gleam + Lustre có thể trở thành Elm mới

    • Với tư cách là backend developer, Elm từng rất hấp dẫn với tôi, nhưng tôi dần rời xa vì xung đột với tác giả và việc ngừng phát hành. Dù vậy, kiến trúc đó vẫn hữu ích trong các dự án khác
    • Gần đây tôi cũng làm một ứng dụng nhỏ bằng Gleam + Lustre, và nó hoạt động tốt hơn hẳn Elm + PostgREST. Giờ tôi định dùng nó cho cả những dự án lớn hơn
    • Tôi đã xem qua Lustre, nhưng hệ sinh thái vẫn còn nhỏ. Thậm chí không có ví dụ về xác thực nên tôi chuyển sang LiveView. Dù vậy ergonomics rất tốt nên tôi hy vọng nó sẽ phát triển
  • Dạo này tôi băn khoăn liệu trong thời đại LLM, việc học ngôn ngữ mới còn đáng giá hay không
    Nếu đó là ngôn ngữ mà LLM chưa học, tôi lo tính hữu dụng như một công cụ của nó sẽ giảm đi

    • Về lâu dài, nếu LLM không thể học ngôn ngữ mới, thì đó là thất bại đối với mục tiêu trở thành trí tuệ tổng quát
    • Cách đây 1–2 năm thì lo ngại đó còn có lý, nhưng giờ Claude Code cũng viết Elixir khá tốt. Dữ liệu huấn luyện ít cũng không thành vấn đề
    • Claude cũng xử lý Gleam tốt. Tài liệu và chất lượng thông báo chẩn đoán rất tốt nên LLM dễ học. Nó đưa ra chẩn đoán ở mức Rust
      Trong khi đó Swift có cú pháp phức tạp nên LLM khó xử lý hơn
    • Nếu xem ngôn ngữ như một công cụ, thì thiếu nhu cầu thị trường có thể còn là rào cản lớn hơn
    • Tôi hy vọng các ngôn ngữ mới sẽ không bị khựng lại vì giới hạn của LLM
  • Trước đây khi xem Gleam, tôi thấy có vẻ nó không có dynamic dispatch (interface hay type class), không biết giờ thì sao

    • Thường người ta giải quyết bằng kiểu “truyền vào một struct hàm”. Cách tiếp cận tường minh này lại hay vì tránh được độ phức tạp của generic
    • Gleam hỗ trợ first-class function, nên có thể làm dynamic dispatch. Type class hay interface rốt cuộc cũng có thể biểu diễn bằng higher-order function
  • [first, ..rest] hay [first, second] thì được, nhưng [first, ..middle, last] thì không.
    Có lẽ họ cố ý chặn vì chi phí quá cao

  • May mắn là cảnh sát tiêu đề blog đã nhanh chóng xuất hiện
    Liên kết liên quan