Hướng dẫn làm phẳng đường cong học Rust
(corrode.dev)- Rust là ngôn ngữ đòi hỏi một cách tư duy hoàn toàn mới, và tư duy tiếp cận ảnh hưởng rất lớn đến tốc độ học
- Làm quen với compiler là chìa khóa; điều quan trọng không phải chỉ là sửa lỗi, mà là hiểu lý do đằng sau thông báo lỗi
- Ở giai đoạn đầu, nên chủ động dùng
clone(),unwrap... để bắt đầu từ nhỏ rồi tái cấu trúc dần dần - Cần tự tay viết nhiều code, tích lũy trực giác và trí nhớ cơ bắp qua lỗi sai và thử-sai
- Rust có triết lý phát triển lấy hệ thống kiểu làm trung tâm, nên cần đọc tài liệu kỹ và luyện mô hình hóa bằng kiểu
Flattening Rust's Learning Curve
Rust nổi tiếng là ngôn ngữ khó học, nhưng bài viết này đưa ra những lời khuyên cụ thể về thái độ và cách tiếp cận để học Rust hiệu quả hơn, dựa trên kinh nghiệm thực tế của tác giả
Let Your Guard Down
- Rust đòi hỏi một mô hình tư duy khác với các ngôn ngữ hiện có
- Có trường hợp người mới học nắm bắt nhanh hơn cả người có kinh nghiệm → thái độ và sự cởi mở là yếu tố then chốt
- Không nên coi borrow checker là kẻ thù mà là đồng tác giả; cần nỗ lực hiểu các thông báo lỗi
- Điều quan trọng là phải có tinh thần muốn hiểu thật sâu vì sao compiler lại yêu cầu lifetime parameter
- Code càng xấu mắt và phức tạp thì càng có thể là dấu hiệu của thiết kế sai, và nên xem đó là cơ hội để tìm cách tốt hơn
- Tính dài dòng (verbosity) của Rust có ích cho các ứng dụng quy mô lớn và thuận lợi cho việc refactor
- Nên bật và tận dụng mọi lint của
clippyngay từ đầu
Baby Steps
- Ban đầu có thể thoải mái dùng
String,clone(),unwraprồi refactor sau - Hãy bắt đầu từ các câu lệnh
if,matchđơn giản thay vì chuỗi method phức tạp - Nên tránh async trong tuần đầu tiên
- Học bằng cách thử nghiệm các đoạn code nhỏ trong Rust Playground
- Mỗi khái niệm nên thực hành với một file
main.rs, và hãy viết phần lớn code với tâm thế sẵn sàng bỏ đi
Be Accurate
- Với Rust, độ chính xác là điều kiện để tồn tại
- Lỗi gõ sai hoặc sai sót nhỏ cũng có thể lập tức dẫn đến lỗi biên dịch, nên cần cẩn thận
- Hình thành thói quen tự động thêm
&,mutsẽ rất hữu ích - Các video stream của những lập trình viên như
Tsodinglà tài liệu tham khảo tốt
Don’t Cheat
- Phụ thuộc vào LLM hay tự động hoàn thành code sẽ làm chậm quá trình học
- Cần tự tay gõ code, và khi không hiểu thì tập tra cứu tài liệu
- Đừng code trong trạng thái auto-pilot
- Hãy chấp nhận sai lầm và dùng chúng để hiểu compiler hoạt động như thế nào
- Cũng nên luyện dự đoán xem code có biên dịch được hay không trước khi chạy
- Thói quen đọc và phân tích code của người khác cũng rất quan trọng
- Trong lúc học, nên hạn chế dùng crate bên ngoài, chỉ xem
serde,anyhowlà ngoại lệ tương đối chấp nhận được
Build Good Intuitions
- Các khái niệm như
lifetime,ownershipsẽ dễ nắm hơn nếu hiểu theo cách trực quan - Nên tập dùng các công cụ như
excalidrawđể tự vẽ luồng dữ liệu và kiến trúc - Nhiều kỹ sư và nhà toán học xuất sắc cũng tận dụng rất tốt công cụ trực quan hóa
Build On Top Of What You Already Know
- Rust có thể vận hành khác đi ngay cả với những khái niệm quen thuộc (ví dụ:
mut, value move...) - Tuy vậy, học bằng cách đối chiếu với các ngôn ngữ sẵn biết vẫn rất hữu ích
Ví dụ:
- Trait → giống Interface nhưng không hoàn toàn giống
- Struct → cảm giác như class không có kế thừa
- Closure → tương tự lambda
- Module → namespace
- Borrow → con trỏ sở hữu đơn
- Option → Maybe monad
- Enum → algebraic data type
- Rosetta Code rất hữu ích cho việc học bằng cách so sánh code giữa nhiều ngôn ngữ
- Học bằng cách port code từ ngôn ngữ quen thuộc sang Rust cũng rất hiệu quả
- Cũng nên luyện suy nghĩ xem các cú pháp và thành ngữ đặc trưng của từng ngôn ngữ, như list comprehension hay vòng lặp, sẽ được diễn đạt thế nào trong Rust
Don’t Guess
- Rust là ngôn ngữ không dành cho việc đoán mò
- Hãy suy nghĩ vì sao phải viết những đoạn như
"hello".to_string() - Thông báo lỗi cực kỳ hữu ích, nên tuyệt đối đừng bỏ qua các gợi ý ẩn trong đó
- Đặc biệt với lỗi liên quan đến borrow checker, cần tự tay lần theo luồng dữ liệu để phân tích
Lean on Type-Driven Development
- Rust là ngôn ngữ lấy hệ thống kiểu làm trung tâm
- Có thể rút ra rất nhiều thông tin từ function signature hay định nghĩa kiểu
- Hãy thường xuyên đọc tài liệu và source của standard library
- Thiết kế kiểu trước rồi viết code theo kiểu đó sẽ giúp tạo ra cấu trúc chính xác và tái sử dụng tốt hơn
- Nếu biểu diễn invariant bằng kiểu, thì code sai đơn giản là sẽ không thể biên dịch
Invest Time In Finding Good Learning Resources
- Tài liệu học Rust vẫn chưa quá phong phú, nên tìm được nguồn phù hợp với bản thân ngay từ đầu sẽ tiết kiệm rất nhiều thời gian
- Các công cụ học như
Rustlingscó thể hợp hoặc không hợp tùy người - Những tài liệu thiên về giải bài tập, như
Advent of Code,Project Euler, có thể phù hợp hơn - Video YouTube nên được dùng nhiều hơn cho mục đích giải trí thay vì nguồn kiến thức chính
- Cách hiệu quả nhất là mua sách, đọc offline và tự tay viết code
- Nếu có thể, được chuyên gia đào tạo hoặc coaching cũng có thể tiết kiệm rất nhiều thời gian về lâu dài
Find A Coding Buddy
- Quan sát và bám sát như cái bóng cách một đồng nghiệp giỏi viết code cũng là phương pháp tốt
- Có thể nâng cao trình độ bằng cách nhờ review code hoặc tự review trên diễn đàn Rust, Mastodon, v.v.
Explain Rust Code To Non-Rust Developers
- Việc giải thích cho người không biết Rust cũng rất hiệu quả cho học tập
- Cũng nên thử đóng góp cho những đoạn code trong dự án mã nguồn mở không còn được bảo trì tốt
- Sẽ rất hữu ích nếu tự viết một bảng thuật ngữ ánh xạ các khái niệm Rust sang ngôn ngữ nghiệp vụ của công việc mình
Believe In The Long-Term Benefit
- Rust là ngôn ngữ hướng đến chất lượng dài hạn hơn là năng suất ngắn hạn
- Không thể thành cao thủ chỉ sau một đêm, nhưng nếu tập trung một tháng thì có thể thu được rất nhiều
- Rust là một "Day 2 language": ngày đầu thì khó, nhưng giá trị tăng dần khi dùng liên tục
- Muốn thành công, không chỉ học vì CV mà còn phải thực sự yêu thích việc lập trình
4 bình luận
Trước đây tôi từng thử viết lại bằng Rust đoạn mã mà mình đã viết bằng C để học tập, và tôi vẫn còn nhớ trải nghiệm xử lý con trỏ thật sự quá khổ sở... Tôi vẫn chưa thể sắp xếp rõ trong đầu cách hoạt động của
RchayRefCell...Sau khi chỉ đọc một lượt tài liệu cơ bản rồi đến Nomicon theo đúng thứ tự, tôi chưa từng bị vướng chỗ nào với Rust, nên cũng tự hỏi liệu đường cong học tập của nó có thực sự cao đến vậy không.
Ôi, nếu quen tay dùng
unwrapvàclonethì về sau sẽ khổ sở lắm vì ownership, huhuÝ kiến trên Hacker News
Cảm giác như đang đọc “A Discipline of Programming”; cách giải thích mang tính đạo đức của Dijkstra từng rất cần thiết vì ngày xưa mọi người còn chưa thật sự hiểu các khái niệm lập trình. Phần giải thích về ownership trong Rust thường quá dài dòng; hầu hết khái niệm cốt lõi đều có đó nhưng lại bị chôn dưới các ví dụ. Trong Rust, mỗi đối tượng dữ liệu có đúng một chủ sở hữu. Quyền sở hữu này có thể được chuyển đi, nhưng tại mọi thời điểm chỉ có một chủ sở hữu. Nếu cần nhiều chủ sở hữu, thì chủ sở hữu thực sự phải là một ô đếm tham chiếu, và ô đó có thể được sao chép. Khi chủ sở hữu biến mất thì những gì nó sở hữu cũng biến mất. Có thể dùng ref để tạm thời mượn quyền truy cập tới một đối tượng dữ liệu. Ownership và reference là hai thứ khác nhau rõ ràng. Reference có thể được truyền đi và lưu lại, nhưng không thể sống lâu hơn đối tượng mà nó trỏ tới; nếu không sẽ thành lỗi “dangling pointer”. Các quy tắc này được borrow checker cưỡng chế nghiêm ngặt tại thời điểm biên dịch. Đó là mô hình ownership của Rust; nếu hiểu nó thì các chi tiết cuối cùng đều quy về những quy tắc này.
Không biết có phải chỉ mình tôi không, nhưng kiểu giải thích khái niệm thế này rất khó theo dõi; encapsulation cũng từng như vậy với tôi. Người ta chỉ nói là ẩn thông tin, nhưng không đào sâu cụ thể là như thế nào và tại sao. Ví dụ, tôi không hiểu chính xác ai là owner trong Rust. Stack frame là owner à? Với cấu trúc LIFO, tại sao lại chuyển ownership sang callee; nếu stack của callee biến mất trước thì chẳng phải cũng không có rủi ro sao? Nếu là để tối ưu hóa thì có phải để dọn dẹp đối tượng sớm hơn không? Nếu owner không phải stack frame thì nó là cái gì? Tôi cũng không rõ vì sao mutable reference chỉ được cấp một lần. Trong môi trường đơn luồng, trước khi một hàm kết thúc thì hàm khác cũng đâu thể bắt đầu, nên có vẻ cho cả hai cùng nhận mutable reference cũng không sao. Nếu chỉ môi trường đa luồng mới có vấn đề thì đến lúc đó báo lỗi có được không? Chính vì những thắc mắc này mà tôi cứ học Rust được một lúc lại bỏ dở.
Đây không phải là giải thích ownership mà là một cách tạo động lực. Phần khó nhất và cốt lõi nhất là cách đọc các chữ ký hàm có lifetime rối rắm, cũng như cách hiểu và sửa các lỗi biên dịch phát sinh khi gọi những hàm đó.
Làm ra một bản tóm tắt trông đúng và hoàn hảo đối với người đã biết các khái niệm này thì dễ hơn rất nhiều so với việc giải thích cho người mới học. Nếu giải thích kiểu này thì liệu người chỉ quen với call-by-sharing có thể hiểu ngay không? Tôi không nghĩ vậy.
Người không biết Rust mà chỉ đọc bản tóm tắt này xong thì vẫn sẽ chẳng biết gì về Rust. Họ chỉ thấy như thể “ngôn ngữ này chắc có thứ hắc ma thuật nào đó trong compiler”.
Bản thân các khái niệm ownership và borrowing thì dễ hiểu. Điều thực sự khiến Rust khó học là chữ ký hàm và mã sử dụng thực tế phải cùng nhau chứng minh rằng reference không sống lâu hơn đối tượng. Nhân tiện, không lưu đối tượng được tham chiếu vào type sẽ làm việc chứng minh bớt phức tạp hơn, nên đó thường là lựa chọn tốt hơn.
Tôi đã tìm từ lâu những bài viết nói về việc người ta trong thập niên 60 xử lý trạng thái hệ thống/ứng dụng ở cấp độ assembly như thế nào. Tôi nghe nói bài báo Sketchpad của Sutherland có khá nhiều chi tiết về cấu trúc dữ liệu, nhưng mới chỉ đọc chương 2-3.
Cách giải thích này không thật sự có ý nghĩa với tôi. Nó không định nghĩa rõ ownership và borrowing. Cả hai đều giống những từ dựa trên phép ẩn dụ quản lý tài sản tài chính. Tôi không rành Rust, nhưng cảm giác chính cách chọn từ như vậy làm cho khái niệm khó hiểu hơn. Ẩn dụ thường là con dao hai lưỡi. Có lẽ giải thích bằng các thuật ngữ bộ nhớ trực tiếp hơn sẽ hữu ích hơn.
Phần giải thích mô hình đã bỏ hẳn sự khác biệt quan trọng giữa borrow độc quyền/chia sẻ (hoặc mutable/immutable). Rust đã đưa ra rất nhiều lựa chọn về việc cho phép các kiểu borrow này như thế nào, và điều đó không hề trực quan. Ví dụ, quy tắc no aliasing không xuất phát từ trực giác mà từ mục đích tối ưu hóa hàm. Phần phức tạp nhất của borrowing là vì các quy tắc lifetime elision mà thông báo lỗi của compiler đôi khi chỉ vào chỗ hoàn toàn khác với nguyên nhân thật sự. Những quy tắc elision này không trực quan, chúng là các lựa chọn được đưa vào để đơn giản hóa.
Phiên bản sửa đổi của Rust Book do Brown University thực hiện giải thích borrow checker cực kỳ hay.
Có vẻ phần giải thích này chưa đầy đủ. Ví dụ, không nói gì về chuyện điều gì xảy ra khi bên đi mượn biến mất.
Câu “chủ sở hữu thực sự phải là một ô đếm tham chiếu” nghe như chỉ những người đã biết nó là gì mới hiểu được.
Chỉ khi tự tay cài một borrow checker của riêng mình thì tôi mới thực sự hiểu borrow checker.
Mục thứ hai của phần thứ hai bị phóng đại nghiêm trọng. Trên thực tế có vô số trường hợp bạn có thể viết mã an toàn nhưng Rust vẫn không biên dịch. Sự phức tạp này xuất hiện để làm rõ giới hạn của việc compiler có thể chứng minh được điều gì.
Mô hình ownership, lifetime, enum và pattern matching của Rust khi mới tiếp xúc quả thật rất nặng nề. Lần đầu thử tôi bị choáng quá sớm, lần thứ hai thì cố đọc từng dòng trong sách đến mức cạn sạch kiên nhẫn. Trong quá trình đó tôi nhận ra Rust là ngôn ngữ cho mình góc nhìn sâu hơn về lập trình và thiết kế phần mềm. Đến lần thử thứ ba, cuối cùng tôi mới bắt đầu học bằng cách viết lại những chương trình nhỏ và script mình từng dùng theo phong cách Rust, và qua đó dần nắm được cả cách xử lý lỗi kiểu Rust, cách biểu diễn dữ liệu bằng type, và pattern matching. Sau những trải nghiệm đó, tôi tin chắc rằng học Rust là một trong những quyết định tốt nhất trong đời lập trình của mình. Việc định nghĩa trước type, struct, enum và viết hàm dựa trên dữ liệu bất biến cùng pattern matching giờ đã trở thành điều tự nhiên với tôi cả ở các ngôn ngữ khác.
Tôi cũng có trải nghiệm tương tự. Đến lần thứ ba học Rust thì mọi thứ mới bắt đầu vào guồng, và tôi đã có thể viết hiệu quả một vài chương trình. Dù có nhiều năm kinh nghiệm lập trình, đôi khi vẫn phải học lặp lại nhiều lần. Trước đây khi cố hiểu Dagger, framework dependency injection trên JVM, tôi cũng cần đúng 3 lần thử. Có lẽ đó là một kiểu mẫu chung của tôi khi học những thứ phức tạp.
Đây là hiện tượng các lập trình viên C++ thường gặp khi lần đầu tiếp xúc Rust: nếu tiếp cận bằng tư duy C++ thì sẽ liên tục “đánh nhau” với borrow checker. Khi thật sự nắm được các quy ước của Rust, bạn lại mang các quy ước đó ngược về C++ và viết mã chắc chắn hơn, dù C++ không có borrow checker.
Lời khuyên kiểu “hãy đọc thật kỹ toàn bộ mã trước khi biên dịch và sửa lỗi gõ nhầm” nghe khá lạ. Rust compiler vốn nổi tiếng vì thông báo lỗi rất thân thiện, vậy tại sao tôi phải ngồi dò typo; tôi muốn máy tính làm chuyện đó giúp mình.
cargo fixcó thể tự động sửa một số vấn đề, nhưng không giải quyết được tất cả.Có những lời khuyên như “đừng chống lại”, “muốn học thì phải bỏ cái tôi”, “cần tuyên bố đầu hàng”, “kháng cự là vô ích, không chấp nhận sớm thì chỉ kéo dài đau khổ”, “hãy quên những gì bạn biết”. Nghe thế tôi cứ nghĩ hệ điều hành telescreen của Orwell chắc được viết bằng Rust.
Rust có một rào cản khá lớn với người mới. Nó rất khác các ngôn ngữ khác — có chủ đích, nhưng cũng vì thế mà khó bước vào. Cú pháp phức tạp và cực kỳ cô đọng, nhìn như thể ai đó gõ bàn phím bằng khuỷu tay. Chỉ một ký tự cũng có thể đổi hẳn ý nghĩa, và mức độ lồng nhau thì cao. Nhiều tính năng khó hiểu nếu không có nền tảng lý thuyết, khiến độ phức tạp càng tăng; hệ thống type và cơ chế borrowing là ví dụ điển hình. Với người dùng Python hay JavaScript thông thường thì gần như là tiếng người ngoài hành tinh. Trong thời đại mà phần lớn lập trình viên thực tế không có nền tảng CS tầm cao học, Rust có vẻ không phù hợp. Thêm vào đó macro còn làm mọi thứ phức tạp hơn nữa; nếu không biết phần định nghĩa thì rất khó hiểu mã đang muốn nói gì. Gần đây tôi kỳ vọng LLM có thể hạ thấp rào cản này. Dù hiện tại tôi vẫn chưa thấy cần phải học Rust, nhờ LLM mà có lẽ một ngày nào đó tôi sẽ thử lại. Rust đúng là một ngôn ngữ khó học theo kiểu rất riêng.
Có vẻ trong mọi tình huống đều sẽ có lựa chọn tốt hơn Rust. Dù vậy tôi vẫn giữ đầu óc cởi mở. Có lẽ khi nào Rust trở nên đủ phổ biến thì lúc đó nó mới có ý nghĩa.
Nếu một ngôn ngữ đến mức cần có cả những bài viết đi thuyết phục mọi người phải cố học nó, thì tôi nghi ngờ liệu có phải bản thân thiết kế ngôn ngữ đã có vấn đề hay không. (Tôi chưa học Rust nên đừng xem quá nghiêm trọng.)
Tôi chỉ có thể đọc bình luận của bạn theo kiểu “cái gì khó thì không đáng làm”. Mọi thứ đều có ưu và nhược điểm; chẳng lẽ chỉ vì có nhược điểm mà không đáng thử sao? Nếu ai đó nhiệt tình viết về việc chơi đàn hạc rất khó, thì chơi đàn hạc là một sở thích tệ à?
Khi trở thành lập trình viên senior, nhiều khi người ta đã từng liếc qua những bài học mà Rust coi trọng nhưng chưa thật sự cảm nhận sâu. Nhiều người nghĩ “tôi đã dùng ngôn ngữ có garbage collection rồi, Rust còn dạy được gì chứ”. Trên thực tế, khi tính khả biến và shared reference đan xen vào nhau thì hỗn loạn khủng khiếp sẽ xuất hiện, vì thế người ta bắt đầu dùng nhiều immutable object hơn. Nhưng khi đã có immutable object thì lại phải tìm cách biến đổi chúng một cách tiện lợi, và đôi khi điều đó còn kém tiện dụng hơn mutable object. Khi cố biểu đạt rằng “đối tượng này có lúc có thể thay đổi và có lúc là bất biến”, cuối cùng bạn sẽ thấy cần borrow checker. Khi borrow checker xuất hiện thì lại nảy ra câu hỏi “vậy tại sao vẫn cần garbage collection?”. Cuối cùng người ta dùng garbage collection chỉ vì ngại phải hiểu thật rõ lifetime của đối tượng. Rust cho bạn trực tiếp trải nghiệm những câu hỏi nền tảng này.
Các quyết định thiết kế của Rust nhiều lúc rất khó hiểu. Mojo cũng có borrow checker, nhưng dễ học hơn Rust rất nhiều nhờ vài lựa chọn. Thứ nhất là value semantics. Trong Rust, người mới thường được bảo cứ dùng
clone()trước đã, trong khi ở các ngôn ngữ tĩnh thông thường (C, C++, Go...) thì value semantics vốn đã là mặc định. Thứ hai là lifetime trong Mojo dùng để quyết định thời điểm xóa chứ không phải để quyết định một giá trị còn có thể được dùng theo phạm vi hay không. Nếu còn reference thì lifetime được kéo dài, và khi dùng xong thì xóa ngay. Vì vậy trong Mojo bạn không phải gặp kiểu lỗi “giá trị không sống đủ lâu”. Chỉ hai lựa chọn thiết kế này thôi cũng đã giảm tải rất nhiều.Với người mới thì ngôn ngữ nào cũng khó học, nên không thể nói riêng Rust là đặc biệt. Lập trình vốn dĩ đã có đường cong học tập.
Theo tôi, sự tồn tại của những bài viết như thế này nói nhiều hơn về tác giả hơn là về ngôn ngữ. Không phải để chê tác giả; tôi thấy thật tuyệt khi ai đó chia sẻ đam mê như vậy.
Bài viết này dường như chỉ nói về đường cong học tập của Rust chứ không nói Rust giải quyết vấn đề gì. Cần trình bày cân bằng cả hai mặt thì mới có thể kết luận rằng nó có đáng để dấn thân hay không.
Có thể tranh luận bao nhiêu cũng được về các quyết định thiết kế của Rust, nhưng chỉ riêng việc cần có một bài viết như thế thì chưa đủ để đánh giá bản thân ngôn ngữ Rust. Thậm chí tôi còn nghĩ Python mới là ngôn ngữ cần những bài như vậy hơn. Khi số lập trình viên không có nền tảng kỹ thuật ngày càng tăng, Python nghịch lý thay lại là ngôn ngữ ai cũng dùng được còn Rust thì không phải ai cũng dùng được. Với một số người, Rust dễ học hơn rất nhiều nếu so với C, Zig và các ngôn ngữ tương tự. Tôi cũng yêu Python, nhưng nhận thức rõ rằng về căn bản nó là một ngôn ngữ khủng khiếp. Trong thời đại LLM, người ta cũng không thật sự biết rằng cần viết Python tối ưu; mấy người bạn AI của chúng ta nếu không được chỉ dẫn thì cũng sẽ cứ tạo ra Python kém hiệu quả mà thôi.
Với câu hỏi “liệu đó có phải vấn đề thiết kế ngôn ngữ không?”, phản ứng của tôi là “tại sao lại thế?”
Nói với tư cách người đã học Rust: ngay cả khi chủ yếu chỉ dùng Python, tôi chưa từng cảm thấy Rust có khuyết điểm ngôn ngữ nào. Ngược lại, đây là ngôn ngữ rất nghiêm khắc, nên càng cố làm theo kiểu không-Rust thì càng khổ. Nếu làm theo phong cách Rust, càng phức tạp nó lại càng giúp ích lớn hơn. Ở các ngôn ngữ khác, lỗi thường bị phát hiện lần lượt khi chạy; còn với Rust, gần như mọi thứ đều bị bắt ngay lúc biên dịch. Dĩ nhiên nó không chặn được lỗi logic, nhưng có thể xử lý nhờ tích hợp kiểm thử mạnh mẽ. Rust có nhược điểm, nhưng chắc chắn đáng để học thử một lần. Cách Rust giảm lỗi cũng có thể trở thành thói quen tốt khi phát triển ở những ngôn ngữ khác.
Đúng là Rust phức tạp đến mức LLM khó có thể tạo ra mã Rust đúng ngay trong một lần. Dù vậy tôi vẫn thấy điều đó tốt hơn rất nhiều so với hàng loạt vấn đề của JavaScript và các ngôn ngữ yếu kiểu/động khác.
Tôi đã học Rust và đồng cảm với ý bạn. Rust thực sự phức tạp, đúng kiểu ngôn ngữ “thiết kế bởi ủy ban”. Tooling thì tuyệt vời, và dù vẫn ít phức tạp hơn C++, nó tuyệt đối không phải ngôn ngữ dễ học.
Vấn đề của những bài viết kiểu này là chúng không chạm tới bản chất. Có những chương trình mà Rust đơn giản là không cho phép bạn viết. Điều đó có lý do chính đáng, nhưng nó khác về bản chất so với gần như mọi ngôn ngữ mà mọi người từng dùng. Rõ ràng có những chương trình không thể viết bằng Rust, nên hoặc bạn chấp nhận điều đó, hoặc Rust không phù hợp với bạn.
Một cách tiếp cận ít người dùng khi học Rust là trước tiên chỉ học một phần của ngôn ngữ. Ví dụ, trong sách nhập môn Rust của tôi thì hoàn toàn không dạy lifetime. Chỉ với các hàm không có lifetime bạn vẫn có thể viết ra những chương trình chạy tốt. Macro cũng vậy, tuy không dễ nhưng dù sao cũng nên học theo từng tập con trước. Và thay vì ngay từ đầu chỉ dựa vào
copy()hayclone(), tôi nghĩ cách đúng hơn là học khái niệm borrowing trước, vì borrowing là cốt lõi của ngôn ngữ.Cách duy nhất để học Rust là phải có thật nhiều công việc trả trên 300 nghìn đô một năm. Tôi cũng nghĩ Rust có tiềm năng thay C++ trong giới quant về sau. Nhưng OCaml đã có sẵn rồi, và nếu phải học một ngôn ngữ cực khó, cực phức tạp thì trước hết phải thấy tiền đã. Từ trước đến nay các công việc lương cao nhất mà tôi thấy vẫn là Python.
Nhìn các bình luận này, tôi nhận ra một thái độ thường thấy ở các lập trình viên lâu năm khi bị góp ý. Càng làm lâu người ta càng dễ trở nên cố chấp. Mỗi người nên tự nghĩ xem vì sao mình lại từ chối các đề xuất của compiler, nên tự xem mình đang muốn làm gì khác đi, và điều gì thật sự đang cản trở mình.