36 điểm bởi GN⁺ 2025-08-23 | 1 bình luận | Chia sẻ qua WhatsApp
  • Rust là một ngôn ngữ có nhiều khái niệm đan xen chặt chẽ với nhau, nên ngay cả để hiểu một chương trình cơ bản cũng phải học đồng thời nhiều yếu tố
  • Hàm, generic, enum, pattern matching, trait, tham chiếu, ownership, Send/Sync, Iterator... đều là những yếu tố cốt lõi được thiết kế để tương tác với nhau
  • So với JavaScript, JS cho phép viết code chỉ với việc hiểu một phần khái niệm, nhưng với Rust, chỉ khi hiểu được ngữ cảnh của toàn bộ ngôn ngữ thì mới có thể viết ra code thực sự có ý nghĩa
  • Sự phức tạp này của Rust làm tăng rào cản học tập, nhưng đồng thời mang lại tính an toàn và nhất quán, và có ảnh hưởng lớn tới cách thiết kế code
  • Cấu trúc ngôn ngữ như vậy chính là điều làm Rust trở nên đặc biệt, và tầm nhìn về “Rust nhỏ hơn” khiến ta nhìn lại triết lý ngôn ngữ được kết hợp một cách tinh vi

Sự khó khăn khi học Rust

  • Dù Rust có rào cản gia nhập cao, nhiều người vẫn đã đóng góp vào việc cải thiện tài liệu, API và chẩn đoán lỗi
  • Các khái niệm nền tảng bao gồm hàm như công dân hạng nhất, enum, pattern matching, generic, trait, tham chiếu, borrow checker, an toàn đồng thời, iterator
  • Những khái niệm này phụ thuộc lẫn nhau và đan xen với nhau, nên khó học từng phần một cách tách biệt; ngay cả thư viện chuẩn cũng tận dụng hầu hết các tính năng đó
  • Ngay cả để hiểu một đoạn mã Rust khoảng 20 dòng, cũng cần đồng thời nắm được nhiều yếu tố như mô hình hàm, Result và xử lý lỗi, kiểu generic, enum, iterator...

So sánh Rust và JavaScript

  • Khi viết cùng một chương trình theo dõi thay đổi tệp bằng Rust và JS, Rust cho thấy nhiều khái niệm ngôn ngữ đan cài với nhau
  • Với JS, về cơ bản chỉ cần hiểu hàm và xử lý null là đã có thể viết được code chạy ổn
  • Điều này không đơn thuần có nghĩa là Rust khó hơn, mà cho thấy Rust là một thiết kế đòi hỏi sự hiểu biết có cấu trúc về toàn bộ ngôn ngữ

Thiết kế liên kết chặt chẽ của Rust

  • Cốt lõi của Rust là sự kết hợp của các tính năng được thiết kế một cách hữu cơ
    • Enum sẽ bất tiện nếu không có pattern matching, và pattern matching cũng bị hạn chế nếu không có enum
    • ResultIterator không thể được triển khai nếu không có generic
    • Các khái niệm Send/Sync và ràng buộc của println chỉ có thể được biểu đạt an toàn khi có trait
    • Borrow checker bảo đảm an toàn Send/Sync thông qua việc phân tích capture của closure
    Quảng cáo
  • Sự gắn kết lẫn nhau này khiến Rust trở thành một hệ thống ngôn ngữ tích hợp, chứ không chỉ là tập hợp đơn thuần của các tính năng

Tầm nhìn về Rust nhỏ hơn

  • Năm 2019, without.boats đã nhắc đến “Smaller Rust” khi bàn về khả năng của một Rust nhỏ gọn và tinh lọc hơn
  • Ngày nay Rust đã lớn hơn rất nhiều, nhưng khái niệm Rust nhỏ hơn vẫn nhắc lại bản chất của một thiết kế ngôn ngữ được ăn khớp tinh vi
  • Sức hấp dẫn của Rust nằm ở chỗ các yếu tố ngôn ngữ vừa độc lập vừa khi kết hợp lại tạo ra khả năng biểu đạt mạnh mẽ và tính an toàn

Kết luận

  • Rust khó học, nhưng tính nhất quán và tích hợp của các khái niệm đan xen với nhau lại là một thế mạnh lớn
  • Nhờ cấu trúc đó, Rust khiến lập trình viên không chỉ viết code, mà còn hình thành cách tư duy đồng thời cân nhắc cả an toàn lẫn hiệu năng
  • Bản chất của Rust nằm ở một “ngôn ngữ cốt lõi nhỏ gọn và tinh vi”, và đó vẫn là một triết lý quan trọng ngay cả trong Rust đã được mở rộng như ngày nay

1 bình luận

 
GN⁺ 2025-08-23
Ý kiến trên Hacker News
  • Tôi thấy khá mỉa mai khi ngay cả một chương trình JS "đơn giản" cũng có bug. Tài liệu fs.watch ghi rõ rằng trong callback phải kiểm tra trường hợp filename có thể là null. Với Rust, thực tế này sẽ được phản ánh trong hệ thống kiểu và buộc bạn phải xử lý, còn trong JS thì rất dễ viết đại cho xong. Tài liệu liên quan
    • Nếu dùng Typescript thì việc kiểm tra null sẽ bị bắt buộc. Vì vậy đây là một ví dụ hay cho thấy TS là một bước tương đối nhẹ nhàng để đưa JS tiến gần hơn tới tính đúng đắn kiểu Rust
    • Còn có thêm một bug nữa: for path in paths phải là for (const path of paths). JS sẽ báo lỗi ngay nếu thiếu ngoặc, nhưng khác biệt giữa inofin sẽ lặp qua chỉ số của iterable chứ không phải giá trị, nên thực tế chỉ số sẽ bị chuyển thành string rồi đi vào đối số đầu tiên của fs.watch. Thậm chí TypeScript cũng có thể không bắt được lỗi này
    • Đúng như đã chỉ ra, bản thân cú pháp vòng lặp cũng không chính xác, và chỉ cần chạy thử là biết ngay. Tức là có lẽ nên hiểu rằng tác giả không hề chăm chút cho đoạn JS đó, và nó cũng không quá quan trọng đối với luận điểm chính
    • Có thể tôi đã bỏ sót, nhưng tôi thắc mắc kind đến từ đâu. Trong console.log("${kind} ${filename}") thì đúng ra phải là eventType (một string), chứ không phải kind
  • Tôi muốn bắt bẻ một chi tiết nhỏ. println của Rust chỉ in được các kiểu có triển khai trait Display hoặc Debug. Vì thế Path không thể in trực tiếp. Không phải mọi OS đều lưu path theo UTF-8, trong khi kiểu string của Rust thì toàn bộ là UTF-8. Nghĩa là việc in Path có thể gây mất mát dữ liệu. Path trả về một kiểu có triển khai Display thông qua phương thức display. Rust đã đưa điều này vào hệ thống kiểu, nhưng trong JS/TS thì rất khó thể hiện chuyện string nội bộ là UTF-16, và path không phải Unicode thì phải dùng trực tiếp TextEncoder/TextDecoder mới xử lý đúng được. Từ kinh nghiệm trước đây, nếu server gửi text bằng Shift_JIS mà đọc bằng response.text() thì ở runtime chỉ ra chuỗi rỗng. Nếu không quen với vấn đề encoding thì có thể mất vài ngày chỉ để debug chuyện này. Ngoài ra ví dụ JS có bug và lỗi cú pháp mà code Rust không có (trong vòng lặp cần for-of thay vì for-in). Cũng khó nói ví dụ này chỉ dùng "hàm hạng nhất"; bạn vẫn cần hiểu iterator như Rust, lại còn dùng CommonJS. Rồi còn phải học thêm async/await, Promises và top-level await, mà top-level await thì chỉ mới được hỗ trợ gần đây ở một số runtime, bao gồm node. Vẫn còn những JS engine không hỗ trợ, ví dụ Hermes của React Native
    • Đó là lý do tôi vẫn tiếp tục dùng Rust. Đây chỉ là một ví dụ, nhưng những vấn đề vặt vãnh và cạm bẫy kiểu này luôn có mặt đầy rẫy ở các ngôn ngữ khác. Từng cái riêng lẻ có thể không xảy ra, nhưng cộng dồn trong toàn bộ vòng đời chương trình thì chỗ này chỗ kia cứ liên tục xuất hiện bug kỳ quặc và bạn phải không ngừng truy tìm. Trong Rust thì chuyện đó không xảy ra. Hệ thống kiểu chặn trước một lượng trường hợp vô lý đến mức phi thường. Thực tế là sau khi tôi phát hành phần mềm đã hoàn thiện tính năng bằng Rust, về sau chỉ thỉnh thoảng thêm tính năng mới, còn công việc sửa bug thông thường gần như biến mất. Dĩ nhiên ở đâu cũng có thể có bug logic, nhưng Rust chặn tận gốc những vấn đề xuất phát từ sự lệch kiểu/cấu trúc ngớ ngẩn như trong các ngôn ngữ khác, nên trải nghiệm về năng suất và bảo trì hoàn toàn khác

    • Cá nhân tôi cảm thấy không có nhiều lập trình viên JS/TS thực sự hiểu tử tế về thenable/Promise và async-await. Tôi từng thấy cả những thứ như thế này:

      var fn = async (param) => new Promise((res, rej) => {
        fooLibraryCall(param).then(res).catch(rej);
      });
      

      Họ bọc nguyên wrapper kiểu callback vào Promise rồi lại dùng nó bên trong một hàm async. Mỗi lần gặp kiểu này tôi thấy rất đau lòng. Tôi thực sự thấy code như vậy ở khắp nơi. Ngoài ra, nếu tính cả import module và async import(), transpile, code splitting, v.v. thì đúng là rất phức tạp

  • Tôi nghĩ câu trích dẫn của Bjarne thực ra là một bài chào hàng nhằm liên tục biện minh cho việc C++ ngày càng tệ hơn. Lúc đầu có thể là chân thành, nhưng bây giờ mô hình này cứ lặp lại. Cấu trúc của nó theo tôi là thế này:
    1. "Bên trong C++ có một ngôn ngữ nhỏ hơn và gọn gàng hơn"
    2. Nhưng không thể tách một subset ra khỏi ngôn ngữ, nên trước hết hãy tạo một superset (đa tính năng hơn), rồi sau đó mới làm subset
    3. Superset đó được đưa vào C++N+1. Còn cuộc thảo luận về subset thật sự thì lại để sau, rồi cứ lặp lại
    4. C++N+1 trở nên phức tạp hơn, và cứ thế lặp mãi mãi Những người đã nhìn thấy chuyện này lặp đi lặp lại hẳn sẽ không hiểu vì sao người khác vẫn ở lại. Rốt cuộc cái "ngôn ngữ nhỏ hơn và gọn gàng hơn" ấy chẳng bao giờ xuất hiện. Lúc nào cũng chỉ đang lặp lại bước một
    • Nó làm tôi nhớ tới xkcd 927 xkcd 927. Mỗi chuẩn C++ mới lại càng phức tạp hơn; tuy cũng có thay đổi tốt, nhưng cũng thường không ăn khớp lắm với các phiên bản cũ và mã nguồn thì ngày càng rối. Tôi đang duy trì hai thư viện OSS nhưng giờ hầu như không còn dùng nữa. Gần đây tôi hay tự hỏi mình sẽ còn chịu đựng được đến bao lâu. Rust mang lại cảm giác rất sảng khoái sau khi chuyển từ c++11/14/17/20 sang. Tuy vậy, nếu phải nắm hết mọi thứ thì Rust cũng đủ rộng lớn. Những gì bài viết này chỉ ra khiến tôi thấy rất đúng
  • Không ai thấy mất tập trung ngay khi nhìn thấy shebang (rust script tự thực thi) à? Tôi đã ngạc nhiên y như lần trước thấy điều tương tự trong Go. Trông khá hữu ích và có vẻ đủ dùng cho các mục đích cơ bản. Tôi cũng từng thấy thứ tương tự trong các dự án quản lý pipeline build/test bằng rust. Với mục đích như vậy thì đây có thể là một phương án thay thế khá ổn. Tuy nhiên, nhìn chung nếu tôi cần script phức tạp hơn một chút so với bash thì tôi dùng Deno+TS. Tôi làm việc với JS lâu nhất (28 năm), sau đó là C# 24 năm. Tôi dùng Node từ thời kỳ đầu. Deno dễ quản lý hơn Node hay Python về mặt chia sẻ/tập trung package. Cargo frontmatter cũng hoạt động tương tự
    • Tôi chính là người đã tự thiết kế/triển khai việc tích hợp script vào cargo (trước đó cũng đã có nhiều triển khai bên thứ ba). Tôi rất vui khi thấy các trường hợp sử dụng thực tế và càng vui hơn khi thấy nó được nhắc đến. Hãy xem thêm tài liệu. Đã có rất nhiều thảo luận kéo dài về việc hình thức nào là phù hợp, liên kết với ngôn ngữ ra sao, và nên giới hạn phạm vi bản phát hành đầu tiên ở mức nào. Hiện tại chúng tôi đang hoàn tất những phần cuối như style guide và cập nhật Rust reference; những việc lớn còn lại là các chi tiết liên quan đến rustfmt, rust-analyzer, sửa bug trong rustc và cải thiện báo lỗi của Cargo. Bản thân tôi hằng ngày vẫn dùng cargo script để viết script tái hiện issue
    • Thực ra chính vì tôi bắt đầu tìm kiếm từ khóa tính năng -Zscript để nghiên cứu mà bị phân tâm sang đây. Nó đã được triển khai từ 2023 và có cả các issue mở trông gần như sắp hoàn thành. Tôi cũng thấy trong kho lưu trữ ZomboDB việc xử lý pipeline build bằng rust, dù chưa hiểu toàn bộ bối cảnh. Tôi muốn nhấn mạnh rằng cargo frontmatter cực kỳ hữu ích cho tính di động của script. Chỉ cần chia sẻ một file duy nhất, rồi có thể lấy dependency và dùng ngay mà không cần cài đặt/khởi tạo bổ sung như Python hay Node.js
    • Có người nói trong Go cũng làm được điều tương tự, nên tôi muốn hỏi liệu có thể giải thích chi tiết hơn không. Nếu là liên kết này thì tôi cũng quan tâm
    • Dù là người đã dùng JS và C# lâu năm, tôi vẫn nghĩ đến năm 2025 mà chọn hệ thống vì những lý do như vậy thì không ổn lắm. Trong 20 năm qua rất nhiều thứ đã tốt lên đáng kể
    • Đây đơn giản chỉ là chức năng cơ bản của Unix. File bắt đầu bằng #!/some/path thì shell chỉ việc chuyển toàn bộ file đó vào stdin của lệnh được chỉ định để thực thi
  • Tôi tò mò chính xác "ngôn ngữ nhỏ hơn và gọn gàng hơn đang xuất hiện bên trong Rust" là ngôn ngữ nào. Theo bài viết thì reference, lifetime, trait, enum, v.v. vẫn đều phải giữ lại để mọi thứ hoạt động, mà như vậy thì gần như chẳng khác Rust là mấy. Ở phần cuối có hai gợi ý là "Rust tôi muốn dùng" và "Rust của quá khứ", nhưng tôi thấy không thật sự thuyết phục. Tôi cũng đã đọc "Notes on a smaller Rust" của withoutboats, nhưng mục tiêu thiết kế của nó khác hẳn Rust, nên thứ đó không phải là đang muốn trở thành Rust mà chỉ cho thấy những bài học có thể rút ra từ Rust khi nghĩ về một ngôn ngữ mới. Nó không phải một ngôn ngữ muốn trở thành Rust, mà là ví dụ về một ngôn ngữ đáp ứng các yêu cầu "mainstream" (ví dụ: GC, đơn giản hóa compile/cú pháp, v.v.). Thứ hai, cũng có chỗ nói rằng "ngôn ngữ mà tôi đã yêu khi lần đầu học năm 2018 chính là cái 'Rust nhỏ hơn' đó", nhưng thực tế từ sau 2018 Rust không thay đổi quá nhiều về bản chất. Việc đổi edition và tương tự phần lớn là cải thiện độ linh hoạt cú pháp; ngoại lệ lớn thật sự chỉ là async và const. Nếu vậy thì chỉ cần nói thẳng rằng "Rust trước khi có async và const thì nhỏ hơn và sạch hơn", nhưng bài viết lại không nói trực diện như vậy nên khá đáng tiếc
    • Nếu nói về một 'Rust nhỏ hơn và sạch hơn' thì Austral là ví dụ hiện lên trong đầu tôi
    • Cũng có lập luận rằng hoàn toàn có thể có một ngôn ngữ đơn giản hơn (nhỏ hơn) nhưng vẫn giữ được các khái niệm cốt lõi của Rust. Ví dụ, nếu bỏ hết Copy trait, reborrowing, deref coercion, tự động into_iter trong vòng lặp, tự động gọi drop khi scope kết thúc (cái này cũng có thể gọi trực tiếp hoặc để compiler báo lỗi), mặc định :Sized trong trait bound, lifetime elision, match ergonomic và nhiều yếu tố tự động hóa/tiện lợi khác, thì bạn có thể có một Rust đơn giản theo kiểu rất cơ học. Nhưng một ngôn ngữ như vậy sẽ cực kỳ khó chịu để dùng hằng ngày. Trớ trêu là nhiều yếu tố trên thực ra lại được thiết kế cho người mới bắt đầu
    • Tôi đã đọc rất kỹ. Ý của tôi quả thật là Rust trước khi có async và const thì nhỏ hơn và sạch hơn. Lý do tôi không nói thẳng là vì tôi có nhiều bạn bè là những người phát triển các tính năng đó. Matklad diễn đạt rất hay trên lobste.rs. Rust năm 2015 hoàn chỉnh hơn và nhất quán hơn, nhưng tầm nhìn của Rust không phải là sự nhất quán tuyệt đối (coherence), mà là trở thành một ngôn ngữ hữu dụng trong công nghiệp
  • Có thể tôi thiên vị, nhưng tôi cho rằng Rust là ngôn ngữ gần với sự hoàn hảo nhất. Borrow checker thì phiền thật nhưng là cần thiết. Nếu là cùng một đoạn code có bug đó trong C thì runtime đã sụp rồi — và cuối cùng bạn vẫn phải sửa bug. Khác biệt là Rust buộc bạn sửa nó trước cả khi compile, còn C thì bạn phải dập lửa lúc nửa đêm. Rust không hẳn là khó, mà đòi hỏi một sự chuyển đổi trong cách suy nghĩ. Cần một cú dịch chuyển mô hình sang việc viết code an toàn và bảo mật hơn. Thay đổi phần lớn đều gây khó chịu, và tôi nghĩ đó là nguồn gốc cơ bản của sự phản kháng với Rust
    • Rust còn xa mới hoàn hảo
      • Theo tôi compiler có quá nhiều tự do trong việc quyết định thời điểm và thứ tự áp dụng Deref. .into() và trait From xử lý chuyển đổi kiểu quá âm thầm. Trong standard library cũng có nhiều hàm "tiện lợi" kiểu này. Cuối cùng kiểu thực của đối tượng trở nên mơ hồ, và khó lần ra mối liên hệ giữa lời gọi hàm với phần cài đặt của nó (dĩ nhiên IDE có giúp phần nào)
      • Việc trả về ngầm (implicit return) che khuất luồng chương trình và dễ gây sai sót. Toán tử dấu hỏi cũng không hợp gu tôi lắm
      • Các module Rust nhỏ bị chia vụn quá mức, nên để làm được việc hữu ích thường phải cần hàng trăm dependency. Muốn build ổn định thì lại phải quản lý riêng và vendor từng thứ, thật sự rất bất tiện
      • Async Rust hiện giờ hoàn toàn hỗn loạn
    • Vấn đề chính không hẳn là với borrow checker, mà là "khối lượng" của chính Rust đã trở nên quá lớn. Với những người từng thích thứ Rust thô ráp và chưa hoàn chỉnh của năm 2018 (bao gồm tôi), Rust hiện tại không còn hấp dẫn lắm. Dĩ nhiên nếu dùng thành thạo thì nó rất mạnh, nhưng tôi vẫn tự hỏi liệu có đáng để bỏ ra chừng đó công sức hay không. Nếu cần một lựa chọn thay thế C/C++ vào năm 2025 thì có lẽ tôi sẽ chọn Zig (ngoại lệ duy nhất là công việc với Postgres, vì hệ sinh thái pgrx thật sự rất độc đáo). Dù vậy, cái gì cũng vẫn hơn là làm việc với C
  • Tôi không nghĩ nên khuyên người mới học ngôn ngữ đầu tiên bắt đầu bằng Rust. Học ngôn ngữ đầu tiên vốn đã khó, mà với Rust thì vì lỗi compiler nên thường còn khó chạy thử được gì cho đến khi code hoàn toàn đúng chuẩn. Điều đó rất dễ gây nản và bỏ cuộc. Tôi sẽ khuyên nên bắt đầu với Python, JavaScript hoặc Lua, làm nhanh một thứ như game rồi lặp đi lặp lại sẽ tốt hơn
    • Trải nghiệm của tôi lại khác. Một kỹ sư ML ở công ty tôi trước đây chỉ biết Python, nhưng muốn đóng góp cho codebase Rust nên tôi chỉ giải thích khoảng một giờ về những điều cơ bản, sau đó họ thích nghi rất nhanh và năng suất tăng ngay. Thực ra khi làm game mà bị crash vì truyền string vào một hàm cần số, thì việc lần ra nguyên nhân mới là thứ tốn thời gian. Trong Rust, compiler chỉ thẳng rằng "ở đây là string nhưng phải là int", nên ngược lại việc debug lại nhanh hơn nhiều. Thay vì mất cả ngày xử lý lỗi compile, bạn không phải mất cả tuần vì lỗi runtime
    • Tôi chính là tác giả câu trích ở đầu blog. Tôi đã dạy Rust như ngôn ngữ đầu tiên cho hơn 400 người, nên thấy những khẳng định trong thread này rất thú vị. Qua thời gian dài trải nghiệm trực tiếp, tôi đã có đủ bằng chứng không chỉ về khả năng mà còn về việc nó vận hành khá tốt
    • Tôi vẫn chưa thực sự chắc. Tôi muốn thấy một nhà giáo dục giỏi thử dùng Rust như ngôn ngữ đầu tiên. Thế hệ đã đổi và trong đại học người ta dùng Python nhiều, nhưng về mặt lý thuyết tôi nghĩ Rust có thể nâng mặt bằng chung của cả cohort khi làm ngôn ngữ đầu tiên (dù tất nhiên cũng có thể tỷ lệ trượt quá cao gây vấn đề hành chính; ngược lại các sinh viên giỏi có thể học được nhiều hơn). Những thứ học được từ Rust, như move assignment hay ý nghĩa của từ khóa const, đôi khi còn giúp bạn đỡ phải mất công gỡ bỏ các thói quen xấu học từ những ngôn ngữ cũ về sau
    • Bình thường tôi muốn khuyên tránh static typing làm ngôn ngữ đầu tiên. Tôi cũng thích static typing, nhưng với người mới thì nó thường chỉ làm tăng thêm bối rối. Lỗi compiler thường mang tính phản sự kiện, và những thông báo kiểu "compiler không thể chứng minh đây không phải none" có thể khó hơn nhiều so với việc để test case làm crash ở runtime rồi tìm ngay đúng chỗ. Nếu tự in giá trị ra từng dòng để troubleshooting thì đa số vấn đề được giải quyết khá nhanh, nhưng mắc kẹt trong lỗi compiler khó hiểu thì có thể loay hoay rất lâu
    • Rust không phải ngôn ngữ tệ nếu bạn có thể tiếp nhận mọi thứ cùng lúc. Vấn đề là không ai học ngôn ngữ theo cách đó cả, và nếu chưa nắm đủ các khái niệm chính thì trong Rust bạn sẽ liên tục vấp váp. Rồi cuối cùng còn có nhiều khái niệm mà ở ngôn ngữ khác bạn hoàn toàn không học được, nên khi chuyển sang ngôn ngữ mới lại có thể tiếp tục nản lòng
  • Trường hợp gần nhất với thứ tôi từng thấy như một "Rust đơn giản" là Gleam. Có vẻ nó được truyền cảm hứng khá nhiều từ Rust
    • Việc nói Gleam được truyền cảm hứng từ Rust là một hiểu lầm. Người tạo ra nó không chính thức nói vậy. Compiler được viết bằng rust, nhưng Gleam khác hoàn toàn về mô hình và runtime đích, nên không phải là một lựa chọn thay thế Rust
    • Nếu muốn một phong cách 'simple rust' khác thì tôi cũng khuyên nên xem fsharp
    • Trang chủ của Gleam có các thông điệp ủng hộ quyền của người da đen, quyền của người chuyển giới và chống phát xít, nên tôi hoàn toàn không quan tâm đến ngôn ngữ này
    • Tôi tò mò liệu có thể làm 3D bằng Gleam không
  • Tôi thấy khó chịu ở chỗ "không giải thích chương trình Rust đang làm gì". Có rất nhiều diễn giải kỹ thuật, nhưng không có phần tóm tắt chương trình thực tế làm gì. Thực ra nó chỉ theo dõi thay đổi file rồi in ra. Chỉ riêng việc triển khai một tác vụ đơn giản như vậy trong Rust mà đã trở nên phức tạp, phải quan tâm đến các chi tiết nội bộ không liên quan tới vấn đề thực tế, điều này cho thấy rất rõ độ khó của ngôn ngữ. Tôi xem sự phức tạp đó vừa là thử thách sẽ phải đối mặt, vừa là rào cản do chính nó tự dựng lên
    • Các ngôn ngữ khác cũng gặp đúng vấn đề đó, nhưng Rust giúp bạn xử lý nó từ sớm. Không phải mọi filename đều có thể in ra được, và phần lớn các ngôn ngữ chỉ đẩy chuyện đó sang cho người dùng. Rust thể hiện rõ lỗi/thất bại qua return type, còn các ngôn ngữ khác thì cần các cơ chế khác như xử lý ngoại lệ. Trông thì có vẻ đơn giản, nhưng thực ra phía Rust có thể còn trực quan hơn
    • Thực ra phần cài đặt đó, xét trong một ngôn ngữ hiệu năng cao, là rất đơn giản. Tất cả đều nằm gọn trong một trang. Vậy chẳng phải như thế đã là một ví dụ đủ đơn giản rồi sao?
    • Giải thích đơn giản không phải lúc nào cũng đồng nghĩa với triển khai đơn giản. XKCD 1425 minh họa chuyện này rất rõ. (Ví dụ: xác nhận một bức ảnh được chụp trong công viên quốc gia thì dễ, nhưng để phân biệt đó có phải ảnh chim hay không thì cần cả nhóm nghiên cứu) xkcd 1425
  • Tôi cảm thấy Rust khá nhất quán và gắn kết về mặt ngữ nghĩa. So với các ngôn ngữ khác, nó ít đóng vai của đường hóa học hơn là đường ăn, tức là ít "đường cú pháp" hơn nên trực quan hơn. Mọi interface thường đi theo mô hình của module mem, nên nếu muốn hiểu chắc cấu trúc interface thì tốt nhất hãy bắt đầu từ std::mem