38 คะแนน โดย GN⁺ 2025-05-14 | 4 ความคิดเห็น | แชร์ทาง WhatsApp
  • Rust เป็นภาษาที่ต้องอาศัย วิธีคิดแบบใหม่โดยสิ้นเชิง และ ทัศนคติ มีผลอย่างมากต่อความเร็วในการเรียนรู้
  • หัวใจสำคัญคือ การทำความคุ้นเคยกับคอมไพเลอร์ และสิ่งสำคัญไม่ใช่แค่แก้ error message ให้หาย แต่ต้อง เข้าใจเหตุผล ของมันด้วย
  • ในช่วงแรกควรใช้ clone(), unwrap ฯลฯ อย่างเต็มที่ เพื่อ เริ่มจากจุดเล็ก ๆ แล้วค่อยรีแฟกเตอร์ทีละขั้น
  • ควร เขียนโค้ดด้วยมือตัวเองให้มาก และสะสมสัญชาตญาณกับความจำของกล้ามเนื้อผ่านความผิดพลาดและการลองผิดลองถูก
  • Rust มีปรัชญาการพัฒนาที่ ยึดระบบประเภทข้อมูลเป็นศูนย์กลาง จึงควรอ่านเอกสารอย่างละเอียดและฝึกการโมเดลด้วย type

Flattening Rust's Learning Curve

แม้ Rust จะเป็นที่รู้กันว่าเป็นภาษาที่เรียนได้ยาก แต่บทความนี้นำเสนอคำแนะนำเชิงรูปธรรมจากประสบการณ์ของผู้เขียน ว่าด้วยทัศนคติและวิธีเข้าหา Rust ให้เรียนได้อย่างมีประสิทธิภาพมากขึ้น

Let Your Guard Down

  • Rust ต้องการ mental model ที่ต่างจากภาษาเดิม
  • บางครั้งผู้เริ่มต้นก็เรียนรู้ได้เร็วกว่าคนเก่ง → ทัศนคติและความเปิดกว้าง คือหัวใจสำคัญ
  • ไม่ควรมอง borrow checker เป็นศัตรู แต่ให้มองว่าเป็นผู้ร่วมเขียน และควรพยายามทำความเข้าใจ error message
  • ควรมีท่าทีที่อยาก เข้าใจอย่างลึกซึ้ง ว่าทำไมคอมไพเลอร์ถึงต้องการ lifetime parameter
  • ถ้า โค้ดดูไม่น่ามองและซับซ้อนมากขึ้น อาจเป็นสัญญาณของการออกแบบที่ผิด และควรใช้เป็นโอกาสในการหาวิธีที่ดีกว่า
  • ความ verbose ของ Rust มีประโยชน์กับแอปขนาดใหญ่ และ เอื้อต่อการรีแฟกเตอร์
  • ควรเปิดใช้และใช้ lint ของ clippy ให้ครบตั้งแต่ช่วงแรก

Baby Steps

  • ในช่วงแรกสามารถใช้ String, clone(), unwrap ได้อย่างไม่ต้องกังวล แล้วค่อยรีแฟกเตอร์ภายหลัง
  • เริ่มจาก if, match แบบง่าย ๆ ก่อน แทนการทำ method chain ที่ซับซ้อน
  • ควรหลีกเลี่ยง async ในสัปดาห์แรก
  • เรียนรู้ด้วยการทดลองโค้ดชิ้นเล็ก ๆ บน Rust Playground
  • ฝึกโดยใช้ไฟล์ main.rs หนึ่งไฟล์ต่อหนึ่งแนวคิด และเขียนโค้ดส่วนใหญ่ด้วยความคิดว่า เดี๋ยวก็ทิ้งได้

Be Accurate

  • Rust เป็นภาษาที่ ความแม่นยำ คือเงื่อนไขของการอยู่รอด
  • การพิมพ์ผิดหรือความผิดพลาดเล็กน้อยสามารถกลายเป็น compile error ได้ทันที จึงต้องระวัง
  • การสร้างนิสัย เติม &, mut แบบอัตโนมัติ จะช่วยได้
  • วิดีโอสตรีมของนักพัฒนาอย่าง Tsoding เป็นแหล่งอ้างอิงที่ดี

Don’t Cheat

  • การพึ่งพา LLM หรือ code autocomplete มากเกินไปจะทำให้เรียนรู้ช้าลง
  • ควร พิมพ์ด้วยมือตัวเองโดยตรง และถ้าไม่เข้าใจก็ฝึกไปค้นเอกสาร
  • อย่าเขียนโค้ดในโหมด auto-pilot
  • ควร ยอมรับความผิดพลาด และใช้มันเพื่อทำความเข้าใจการทำงานของคอมไพเลอร์
  • แนะนำให้ฝึก คาดเดาก่อนรันว่าโค้ดจะคอมไพล์ผ่านหรือไม่
  • การ อ่านและวิเคราะห์โค้ดของคนอื่น ก็สำคัญเช่นกัน
  • ระหว่างเรียนควร หลีกเลี่ยงการใช้ external crate โดยยกเว้น serde, anyhow ได้บ้าง

Build Good Intuitions

  • แนวคิดอย่าง lifetime, ownership จะเข้าใจได้ดีขึ้นหาก มองเห็นภาพ
  • แนะนำให้ใช้เครื่องมืออย่าง excalidraw เพื่อ วาด data flow และสถาปัตยกรรม ด้วยตัวเอง
  • วิศวกรและนักคณิตศาสตร์เก่ง ๆ จำนวนมากก็ใช้ เครื่องมือการทำภาพ ได้อย่างมีประสิทธิภาพ

Build On Top Of What You Already Know

  • แม้จะเป็นแนวคิดที่คุ้นเคย Rust ก็อาจ ทำงานต่างออกไป (เช่น mut, การย้ายค่า)
  • แต่การเรียนรู้ด้วย การเปรียบเทียบกับภาษาเดิม ก็ยังมีประโยชน์

ตัวอย่าง:

  • Trait → คล้าย Interface แต่ไม่เหมือนกัน
  • Struct → คล้ายคลาสที่ไม่มี inheritance
  • Closure → คล้าย lambda
  • Module → namespace
  • Borrow → pointer แบบเจ้าของเดี่ยว
  • Option → Maybe monad
  • Enum → Algebraic data type
  • Rosetta Code มีประโยชน์ต่อการเรียนรู้แบบเปรียบเทียบโค้ดข้ามภาษา
  • การเรียนด้วยการ พอร์ต โค้ดจากภาษาที่คุ้นเคยมาเป็น Rust ก็มีประสิทธิภาพ
  • การฝึกคิดว่าจะแสดง สำนวนเฉพาะของภาษา เช่น list comprehension หรือ loop ใน Rust อย่างไรก็เป็นแบบฝึกที่ดี

Don’t Guess

  • Rust เป็นภาษาที่ ใช้การเดาสุ่มไม่ได้ผล
  • ลองคิดให้ชัดว่าเหตุใดจึงต้องเขียนโค้ดอย่าง "hello".to_string()
  • error message มีประโยชน์มาก อย่ามองข้าม hint ที่ซ่อนอยู่ในนั้นเด็ดขาด
  • โดยเฉพาะ error ที่เกี่ยวกับ borrow checker ควร ไล่ตาม data flow ด้วยมือ เพื่อวิเคราะห์

Lean on Type-Driven Development

  • Rust เป็นภาษาแบบ type system เป็นศูนย์กลาง
  • คุณสามารถได้ข้อมูลมากมายจาก function signature, การนิยาม type ฯลฯ
  • ควรอ่านเอกสารและซอร์สของ standard library บ่อย ๆ
  • การ ออกแบบ type ก่อน แล้วค่อยเขียนโค้ดให้สอดคล้อง จะช่วยให้ได้โครงสร้างที่แม่นยำและนำกลับมาใช้ซ้ำได้มากขึ้น
  • ถ้า แสดง invariant ผ่าน type ได้ โค้ดที่ผิดจะคอมไพล์ไม่ผ่านตั้งแต่แรก

Invest Time In Finding Good Learning Resources

  • แม้ทรัพยากรสำหรับเรียน Rust จะยังมีไม่มากนัก แต่การหาแหล่งเรียนที่เหมาะกับตัวเองตั้งแต่ต้นเป็นเรื่องสำคัญและช่วยประหยัดเวลา
  • เครื่องมือเรียนอย่าง Rustlings อาจถูกใจหรือไม่ถูกใจก็ได้ ขึ้นอยู่กับสไตล์ของแต่ละคน
  • แหล่งเรียนแบบ โจทย์ปัญหาเป็นศูนย์กลาง อย่าง Advent of Code, Project Euler อาจเหมาะกว่า
  • วิดีโอ YouTube ควรใช้เพื่อ ความบันเทิง มากกว่าหวังสาระอย่างเดียว
  • วิธีที่ได้ผลที่สุดคือ ซื้อหนังสือ อ่านแบบออฟไลน์ และลงมือเขียนโค้ดเอง
  • หากเป็นไปได้ การได้รับการสอนหรือโค้ชชิงจากผู้เชี่ยวชาญก็อาจช่วยประหยัดเวลาได้มากในระยะยาว

Find A Coding Buddy

  • การ ตามดูโค้ดของเพื่อนร่วมทางที่เก่งกว่าอย่างใกล้ชิด ก็เป็นวิธีที่ดี
  • สามารถพัฒนาฝีมือได้ด้วยการขอ code review หรือรีวิวให้คนอื่นบน Rust forum, Mastodon เป็นต้น

Explain Rust Code To Non-Rust Developers

  • การลอง อธิบายให้คนที่ไม่รู้จัก Rust ฟัง ก็ช่วยให้เรียนรู้ได้ดี
  • แนะนำให้มีส่วนร่วมกับโค้ดของโปรเจกต์โอเพนซอร์สที่ ไม่มีคนดูแลแล้ว
  • การทำ glossary ที่แมปคำศัพท์ Rust เข้ากับ ภาษาของโดเมนงานตัวเอง ก็มีประโยชน์

Believe In The Long-Term Benefit

  • Rust เป็นภาษาที่มุ่งไปที่ คุณภาพระยะยาว มากกว่าประสิทธิภาพการทำงานระยะสั้น
  • แม้จะยากที่จะเก่งขึ้นในชั่วข้ามคืน แต่ถ้าทุ่มเวลาอย่างจริงจังสักหนึ่งเดือนก็จะได้อะไรกลับมามาก
  • Rust คือ ‘ภาษา Day 2’ วันแรกอาจหนักหน่อย แต่ ยิ่งใช้อย่างต่อเนื่อง คุณค่าก็ยิ่งเพิ่มขึ้น
  • ถ้าอยากประสบความสำเร็จ ต้องไม่ใช่แค่เรียนเพื่อใส่เรซูเม่ แต่ต้อง ชอบการเขียนโปรแกรมจริง ๆ

4 ความคิดเห็น

 
aer0700 2025-05-17

เมื่อก่อนผมเคยลองเขียนโค้ดที่เคยเขียนด้วย C เพื่อการเรียนรู้ใหม่เป็น Rust แต่มีประสบการณ์ว่าการจัดการ pointer ทรมานมาก... พวกการทำงานของ Rc หรือ RefCell ก็ยังจัดระเบียบในหัวไม่ค่อยลงตัว...

 
q8840 2025-05-15

หลังจากอ่านเอกสารพื้นฐานกับ Nomicon ตามลำดับอย่างละรอบแล้ว ผมก็ไม่เคยติดขัดกับ Rust เลย เลยสงสัยว่าเส้นโค้งการเรียนรู้มันสูงขนาดนั้นจริงหรือ

 
freedomzero 2025-05-15

โอ้ ถ้าติดนิสัยใช้ unwrap กับ clone แล้ว ทีหลังจะทรมานมากเพราะเรื่อง ownership แน่ๆ T_T

 
GN⁺ 2025-05-14
ความคิดเห็นใน Hacker News
  • ให้ความรู้สึกเหมือนกำลังอ่าน “A Discipline of Programming” อยู่ วิธีอธิบายเชิงศีลธรรมของ Dijkstra เคยจำเป็นมากในสมัยก่อนเพราะคนส่วนใหญ่ยังไม่เข้าใจแนวคิดการเขียนโปรแกรมกันจริง ๆ การอธิบายเรื่อง ownership ของ Rust มักจะเยิ่นเย้อเกินไป แนวคิดหลักมีอยู่เกือบครบแต่ถูกซ่อนไว้ใต้ตัวอย่างต่าง ๆ ใน Rust วัตถุข้อมูลแต่ละชิ้นจะมีเจ้าของได้อย่างแม่นยำเพียงคนเดียว และ ownership นี้สามารถส่งต่อได้โดยยังคงมีเจ้าของเพียงคนเดียวเสมอ ถ้าต้องการเจ้าของหลายคน เจ้าของที่แท้จริงก็ควรเป็น reference-counting cell ซึ่งสามารถ clone ได้ เมื่อเจ้าของหายไป สิ่งที่เขาถือครองก็หายไปด้วย เราสามารถยืมการเข้าถึงวัตถุข้อมูลชั่วคราวผ่าน ref ได้ ownership กับ reference เป็นคนละอย่างกันอย่างชัดเจน reference สามารถส่งต่อและเก็บไว้ได้ แต่ห้ามมีอายุยืนกว่าวัตถุนั้น ไม่เช่นนั้นจะเกิดข้อผิดพลาด “dangling pointer” กฎเหล่านี้ถูกบังคับใช้อย่างเข้มงวดโดย borrow checker ตอนคอมไพล์ นี่คือโมเดล ownership ของ Rust ถ้าเข้าใจจุดนี้ รายละเอียดอื่น ๆ สุดท้ายก็ย้อนกลับมาที่กฎเหล่านี้

    • ไม่รู้ว่ามีแค่ผมหรือเปล่า แต่ผมตามคำอธิบายแนวนี้ได้ยากมาก encapsulation ก็เหมือนกัน บอกแค่ว่าเป็นการซ่อนข้อมูลแต่ไม่ลงลึกว่าทำอย่างไร/ทำไมถึงเป็นแบบนั้น ตัวอย่างเช่น ผมไม่เข้าใจว่าใน Rust เจ้าของที่แท้จริงคือใคร stack frame เป็นเจ้าของหรือเปล่า? ด้วยโครงสร้างแบบ LIFO ทำไม ownership ถึงต้องย้ายไปที่ callee ด้วย callee stack หายก่อนอยู่แล้ว มันไม่น่าจะอันตรายไม่ใช่หรือ? หรือถ้าเพื่อการ optimize หมายความว่าสามารถจัดการ object ได้เร็วขึ้นหรือ? ถ้าเจ้าของไม่ใช่ stack frame ก็ไม่รู้ว่าเป็นอะไร อีกอย่างก็สับสนว่าทำไม mutable reference ถึงให้ได้แค่ครั้งเดียว ถ้าเป็น single-thread อย่างไรก็ไม่มีฟังก์ชันอื่นเริ่มทำงานก่อนฟังก์ชันนี้จบอยู่แล้ว ดูเหมือนจะให้ mutable reference กับทั้งสองฝั่งก็ได้ ถ้าปัญหาเกิดเฉพาะใน multi-thread ค่อย error ตอนนั้นไม่ได้หรือ? คำถามพวกนี้ทำให้พอจะเรียน Rust ทีไรก็เลิกกลางคันทุกที

    • นี่ไม่ใช่การอธิบาย ownership แต่เป็นการอธิบายแรงจูงใจ ส่วนที่ยากและสำคัญที่สุดจริง ๆ คือวิธีอ่าน function signature ที่ lifetime พันกันซับซ้อน และวิธีเข้าใจพร้อมแก้ compiler error ที่เกิดตอนเรียกใช้ฟังก์ชันแบบนั้น

    • การทำสรุปที่ถูกต้องและสมบูรณ์สำหรับคนที่รู้แนวคิดเหล่านี้อยู่แล้ว ง่ายกว่าการอธิบายให้คนที่เพิ่งเริ่มเรียนมาก ถ้าอธิบายแบบนี้ คนที่เคยเจอแต่ call-by-sharing จะเข้าใจได้ทันทีจริงหรือ? ผมว่าไม่น่าใช่

    • คนที่ไม่รู้จัก Rust ถ้าอ่านแค่สรุปนี้ก็จะยังไม่รู้อะไรเกี่ยวกับ Rust อยู่ดี คงได้แค่ความรู้สึกว่า “ภาษานี้เหมือนมีมนตร์ดำอยู่ในคอมไพเลอร์”

    • แนวคิดเรื่อง ownership กับ borrowing เองเข้าใจได้ไม่ยาก เหตุผลที่ Rust เรียนยากจริง ๆ คือ function signature กับโค้ดใช้งานจริงต้องพิสูจน์ให้กันและกันเห็นว่า reference จะไม่อยู่ยืนกว่าวัตถุ อนึ่ง การไม่เก็บ referenced object ไว้ใน type จะทำให้การพิสูจน์ซับซ้อนน้อยลง จึงมักเป็นทางเลือกที่ดีกว่า

    • ผมหาบทความเกี่ยวกับวิธีที่คนยุค 60s จัดการ state ของระบบ/แอปพลิเคชันในระดับ assembly มานานแล้ว ได้ยินมาว่าใน paper เรื่อง Sketchpad ของ Sutherland มีรายละเอียดด้าน data structure เยอะมาก แต่ผมอ่านไปแค่บท 2-3

    • คำอธิบายนี้สำหรับผมยังไม่มีความหมาย เพราะไม่ได้นิยาม ownership กับ borrowing ให้ชัด ทั้งสองคำดูเป็นคำอุปมาเชิงการจัดการสินทรัพย์ทางการเงิน แม้ผมจะยังไม่คุ้นกับ Rust แต่รู้สึกว่าการเลือกคำแบบนี้เองทำให้เข้าใจแนวคิดยากขึ้น อุปมามักเป็นดาบสองคม ผมคิดว่าการอธิบายด้วยคำที่เกี่ยวกับหน่วยความจำโดยตรงน่าจะช่วยได้มากกว่า

    • คำอธิบายโมเดลนี้ตัดความต่างที่สำคัญมากระหว่างการยืมแบบ exclusive/shared (หรือ mutable/immutable) ออกไปหมด Rust มีการตัดสินใจหลายอย่างเกี่ยวกับการอนุญาตให้ยืมแบบนี้ได้อย่างไร และมันไม่ได้เป็นธรรมชาตินัก เช่น กฎ no aliasing ไม่ได้มาจากสัญชาตญาณ แต่มาจากเป้าหมายด้านการ optimize ฟังก์ชัน ส่วนที่ซับซ้อนที่สุดของการ borrow คือกฎ lifetime elision ทำให้ข้อความ error จากคอมไพเลอร์บางครั้งชี้ไปผิดจุดจากสาเหตุจริง กฎ elision พวกนี้ก็ไม่เป็นธรรมชาติ และเป็นทางเลือกที่ใส่เข้ามาเพื่อทำให้ดูง่ายขึ้น

    • เวอร์ชันปรับปรุงของ Rust Book โดย Brown University อธิบาย borrow checker ได้ดีมากจริง ๆ

    • ดูเหมือนคำอธิบายนี้ยังไม่ครบ เช่น ไม่มีการพูดถึงว่าจะเกิดอะไรขึ้นเมื่อฝั่งที่ยืมอยู่หายไป

    • ที่บอกว่า “เจ้าของที่แท้จริงก็ควรเป็น reference-counting cell” ฟังดูเหมือนอธิบายสำหรับคนที่รู้แล้วว่า thing นั้นคืออะไรเท่านั้น

    • ผมจะเข้าใจ borrow checker ได้ก็ต่อเมื่อได้ลองเขียน borrow checker ของตัวเองเท่านั้น

    • ข้อที่สองในส่วนที่สองเป็นการพูดเกินจริงอย่างมาก ในความเป็นจริงมีหลายกรณีมากที่ Rust จะไม่ยอมคอมไพล์โค้ดที่ปลอดภัย ความซับซ้อนนี้เกิดขึ้นเพื่อทำให้ขอบเขตของสิ่งที่คอมไพเลอร์พิสูจน์ได้ชัดเจนขึ้น

  • โมเดล ownership, lifetime, enum และ pattern matching ของ Rust ทำให้รู้สึกหนักมากตอนเจอครั้งแรก ตอนพยายามครั้งแรกผมโดน overwhelm เร็วเกินไป และครั้งที่สองพอพยายามจะอ่านหนังสือทุกบรรทัดก็หมดความอดทน ระหว่างนั้นกลับเริ่มตระหนักว่า Rust เป็นภาษาที่ทำให้เข้าใจการเขียนโปรแกรมและการออกแบบซอฟต์แวร์ได้ลึกขึ้น พอครั้งที่สามถึงได้เริ่มเรียนจริง ๆ ด้วยการเอาโปรแกรมเล็ก ๆ กับสคริปต์ที่เคยเขียนมาก่อนมาเขียนใหม่ในสไตล์ Rust ระหว่างทางก็ซึมซับทั้งการจัดการ error แบบ Rust การใช้ type เพื่อแทนข้อมูลอย่างจริงจัง และ pattern matching หลังผ่านประสบการณ์แบบนี้ ผมมั่นใจว่าการเรียน Rust เป็นหนึ่งในการตัดสินใจที่ดีที่สุดในชีวิตโปรแกรมเมอร์ของผม ทุกวันนี้การกำหนด type, struct, enum ล่วงหน้า แล้วเขียนฟังก์ชันบนฐานของข้อมูล immutable กับ pattern matching กลายเป็นสิ่งที่ผมนำไปใช้กับภาษาอื่นอย่างเป็นธรรมชาติ

    • ผมมีประสบการณ์คล้ายกัน ตอนเรียน Rust รอบที่สามถึงเริ่มจับทางได้จริง และเขียนบางโปรแกรมได้อย่างมีประสิทธิภาพ แม้จะมีประสบการณ์เขียนโปรแกรมมานาน แต่บางทีก็ต้องเรียนซ้ำหลายรอบ สมัยก่อนตอนทำความเข้าใจ Dagger ซึ่งเป็น dependency injection framework บน JVM ผมก็ต้องพยายามอยู่พอดี 3 รอบเหมือนกัน บางทีนี่อาจเป็นแพตเทิร์นส่วนตัวเวลาเรียนของซับซ้อนก็ได้

    • นี่เป็นสิ่งที่เห็นบ่อยเวลา C++ developer เจอ Rust ครั้งแรก ถ้ายังคิดแบบ C++ ก็จะได้ “สู้กับ borrow checker” ตลอดเวลา แต่ถ้าเข้าใจแนวปฏิบัติแบบ Rust จริง ๆ แล้ว เอาแนวคิดพวกนั้นกลับไปใช้ใน C++ ก็จะเขียนโค้ดได้แข็งแรงขึ้น แม้ C++ จะไม่มี borrow checker ก็ตาม

  • คำแนะนำว่า “อ่านโค้ดทั้งหมดอย่างละเอียดและแก้คำพิมพ์ผิดก่อนคอมไพล์ แล้วเวลาของคุณจะดีขึ้น” ฟังดูแปลกสำหรับผม Rust compiler มีชื่อเสียงเรื่องข้อความ error ที่เป็นมิตรมากอยู่แล้ว ผมเลยไม่เห็นเหตุผลว่าต้องนั่งไล่หาคำพิมพ์ผิดเอง ผมอยากให้คอมพิวเตอร์ช่วยจับให้

    • cargo fix ช่วยแก้ปัญหาบางอย่างได้อัตโนมัติ แต่ไม่ได้แก้ได้ทุกอย่าง
  • มีคำแนะนำอย่าง “อย่าต่อต้าน”, “ถ้าจะเรียนต้องละทิ้งความหยิ่ง”, “ต้องประกาศยอมแพ้”, “การต่อต้านไม่มีประโยชน์ ถ้าไม่ยอมรับเร็ว ๆ ก็แค่ยืดเวลาความทุกข์”, “ลืมสิ่งที่คุณรู้มา” อ่านแล้วทำให้นึกว่า OS telescreen ของ Orwell คงเขียนด้วย Rust

    • เห็นด้วยกับคำพูดนี้ ความผิดพลาดที่ทำให้ผมหงุดหงิดที่สุดตอนเรียน Rust คือพยายามฝืนใช้มันด้วยกระบวนทัศน์แบบ object-oriented พอแค่ยอมรับว่าจะลองทำตามแบบที่ Rust ต้องการ ทุกอย่างก็เริ่มเข้าที่ทันที
  • Rust มีอุปสรรคค่อนข้างสูงสำหรับผู้เริ่มต้น มันต่างจากภาษาอื่นมาก ซึ่งเป็นความตั้งใจของมันเองและจึงกลายเป็นกำแพงเข้าไปด้วย syntax ซับซ้อนและกระชับมากจนดูเหมือนพิมพ์คีย์บอร์ดด้วยข้อศอก ตัวอักษรเพียงตัวเดียวอาจเปลี่ยนความหมายทั้งหมด และยังซ้อนกันหนัก ฟีเจอร์จำนวนมากก็เข้าใจยากหากไม่มีพื้นฐานเชิงทฤษฎี ยิ่งเพิ่มความซับซ้อนเข้าไปอีก ระบบ type และกลไก borrow คือสองตัวอย่างเด่น สำหรับผู้ใช้ Python หรือ JavaScript ทั่วไปมันแทบเป็นภาษาต่างดาว ในยุคที่โปรแกรมเมอร์จำนวนมากไม่ได้มีพื้นฐาน CS ระดับปริญญาโท Rust จึงดูไม่ค่อยเหมาะ ยิ่งไปกว่านั้น macro ก็ทำให้ซับซ้อนขึ้นอีก ถ้าไม่รู้ว่าถูกนิยามไว้อย่างไรก็ยากจะเข้าใจว่าโค้ดหมายถึงอะไร ช่วงหลังผมเริ่มคาดหวังว่า LLM จะช่วยลดกำแพงนี้ได้ ตอนนี้ยังไม่รู้สึกว่าจำเป็นต้องเรียน Rust แต่เพราะ LLM ผมก็ยังอยากลองอีกครั้งสักวันหนึ่ง Rust เป็นภาษาที่เรียนยากอย่างโดดเด่นจริง ๆ

    • สิ่งที่ทำให้ผมลำบากที่สุดตอนเรียน Rust ก็คือ macro นี่แหละ แหล่งเรียนที่ผมใช้หลายแห่งเอา macro เข้ามาตั้งแต่ต้นโดยไม่อธิบาย ทำให้สับสนมาก
  • ดูเหมือนว่าในทุกสถานการณ์จะมีตัวเลือกที่ดีกว่า Rust อยู่เสมอ แต่ผมก็ยังเปิดใจไว้ ถ้าวันหนึ่ง Rust กลายเป็นเรื่องปกติมากพอ บางทีมันอาจเริ่มมีความหมายขึ้นมา

    • ถ้ายึดตามเป้าหมายดั้งเดิมตอนออกแบบ Rust เมื่อเกือบ 20 ปีก่อน มันคือภาษาที่สมบูรณ์แบบสำหรับการสร้างเบราว์เซอร์ใหม่จากศูนย์ และตอนนี้ Rust ก็ครองพื้นที่นี้ไปแล้ว อีกทั้ง “unix” ของผู้สร้างภาษาก็ครองโลกไปแล้ว ไม่มีใครมาแทนที่มันด้วยอะไรอย่าง Ladybird ได้หรอก
  • ถ้าภาษาหนึ่งต้องมีถึงขั้นบทความที่พยายามโน้มน้าวให้คนยอมลำบากเรียนมัน แบบนี้ก็น่าสงสัยว่าอาจมีปัญหาที่การออกแบบภาษาเองหรือเปล่า (ผมไม่ได้เรียน Rust นะ ก็อย่าซีเรียสกับความเห็นนี้มาก)

    • ผมอ่านคอมเมนต์ของคุณออกมาได้แค่ว่า “ของที่ยากไม่คุ้มจะทำ” ทุกอย่างมีทั้งข้อดีและข้อเสีย การมีข้อเสียแปลว่าไม่คุ้มแม้แต่จะลองเลยจริงหรือ? ถ้ามีคนเขียนอย่างกระตือรือร้นว่าการเล่นฮาร์ปนั้นยาก แบบนั้นการเล่นฮาร์ปก็เป็นงานอดิเรกแย่ ๆ หรือ?

    • พอเป็น senior developer แล้ว บางทีคุณอาจเคยเหลือบเห็นบทเรียนที่ Rust ให้ความสำคัญมาแล้ว แต่ยังไม่เคยสัมผัสมันจริง ๆ หลายคนคิดว่า “ฉันก็ใช้ภาษาที่มี garbage collection อยู่แล้ว Rust จะสอนอะไรฉันได้อีก?” ความจริงคือพอ mutability กับ shared reference พันกัน มันสร้างความสับสนอย่างมหาศาล จนทำให้คนเริ่มใช้ immutable object กันมากขึ้น และเมื่อมี immutable object แล้ว ก็จะเริ่มกลับมาคิดใหม่ว่าจะเปลี่ยนแปลงมันอย่างสะดวกได้อย่างไร ซึ่งอาจใช้งานแย่กว่า mutable object เสียอีก ระหว่างพยายามอธิบายว่า “object นี้มีช่วงที่แก้ไขได้และช่วงที่ immutable” ก็สุดท้ายจะเจอความจำเป็นของ borrow checker พอมี borrow checker แล้วก็ตามมาด้วยคำถามว่า “แล้วทำไมยังต้องมี garbage collection อีก?” เราใช้ garbage collection ก็แค่เพราะขี้เกียจทำความเข้าใจ lifetime ของ object ให้ชัดเจน Rust ทำให้คุณได้สัมผัสคำถามพื้นฐานเหล่านี้ด้วยตัวเอง

    • การตัดสินใจด้านการออกแบบของ Rust หลายอย่างเข้าใจยาก Mojo ก็มี borrow checker เช่นกัน แต่เรียนง่ายกว่า Rust มากเพราะมีตัวเลือกบางอย่าง อย่างแรกคือ value semantics ใน Rust มักถูกสอนให้ผู้เริ่มต้นใช้ clone() ไปก่อน แต่ในภาษาสแตติกทั่วไปส่วนใหญ่ (C, C++, Go ฯลฯ) value semantics เป็นค่าเริ่มต้นในชีวิตประจำวัน อย่างที่สองคือ lifetime ของ Mojo มีไว้กำหนดเวลาในการลบ ไม่ได้มีไว้กำหนดว่าค่าจะยังใช้ได้อยู่ตาม scope หรือไม่ ถ้ายังมี reference อยู่ lifetime ก็จะขยายออก และเมื่อเลิกใช้ก็จะถูกลบทันที ดังนั้นใน Mojo คุณจึงไม่ต้องเจอ error ประเภท “ค่านี้มีอายุไม่ยืนพอ” การตัดสินใจออกแบบแค่สองข้อนี้ก็ลดภาระลงไปได้มากแล้ว

    • สำหรับมือใหม่ ภาษาไหนก็เรียนยากทั้งนั้น ดังนั้นคงบอกไม่ได้ว่า Rust พิเศษกว่าภาษาอื่นมากนัก การเขียนโปรแกรมมันก็มี learning curve โดยธรรมชาติอยู่แล้ว

    • ผมว่าการมีบทความแบบนี้สะท้อนเรื่องของผู้เขียนมากกว่าตัวภาษา ไม่ได้หมายถึงการวิจารณ์ผู้เขียนนะ ผมกลับคิดว่าการแบ่งปันความหลงใหลแบบนี้เป็นเรื่องดี

    • บทความนี้ดูเหมือนพูดถึงแต่ learning curve ของ Rust มากกว่าว่า Rust แก้ปัญหาอะไร การจะตัดสินได้ว่าคุ้มจะลองไหม ควรอธิบายทั้งสองด้านให้สมดุล

    • จะถกเถียงเรื่องการออกแบบ Rust ได้เสมอ แต่การที่มีบทความแบบนี้อยู่ ไม่ได้ทำให้ประเมินตัวภาษาได้ง่ายนัก ตรงกันข้าม ผมกลับคิดว่า Python เป็นภาษาที่ต้องการบทความแบบนี้มากกว่า เมื่อมีโปรแกรมเมอร์ที่ไม่ได้มีพื้นฐานด้านวิศวกรรมมากขึ้นเรื่อย ๆ Python จึงกลายเป็นภาษาที่ใคร ๆ ก็ใช้ได้ ขณะที่ Rust ไม่ใช่สำหรับทุกคน สำหรับบางคน Rust เรียนง่ายกว่า C หรือ Zig มาก ผมก็รัก Python นะ แต่ก็ยอมรับว่ามันเป็นภาษาที่น่ากลัวในระดับรากฐาน ในยุค LLM ผู้คนก็ยังไม่ค่อยรู้ว่าควรเขียน Python ที่ optimize แล้วอย่างไร และเพื่อน AI ของพวกเราก็จะยังสร้าง Python ที่ไม่มีประสิทธิภาพต่อไปถ้าไม่สั่งให้ชัด

    • สำหรับคำถามว่า “มันเป็นปัญหาการออกแบบภาษาหรือเปล่า?” ผมก็อยากย้อนถามว่า “ทำไมถึงคิดแบบนั้น?”

    • ในฐานะคนที่เรียน Rust มาแล้ว ต่อให้ใช้ Python เป็นหลัก ผมก็ไม่เคยรู้สึกว่า Rust มีข้อบกพร่องเชิงภาษาเลย ตรงกันข้าม มันเป็นภาษาที่เข้มงวดมาก และถ้าพยายามทำให้มัน “ไม่เป็น Rust” เมื่อไร ก็จะยิ่งเหนื่อยเปล่า ๆ แต่ถ้าทำตามสไตล์ของ Rust ยิ่งระบบซับซ้อนขึ้น มันยิ่งช่วยได้มาก ภาษาอื่นมักเจอ error ทีละอย่างตอนรัน แต่ Rust จับได้แทบทั้งหมดตั้งแต่คอมไพล์ แม้จะกัน logical error ไม่ได้ แต่ก็รับมือได้ด้วยการผสานการทดสอบที่แข็งแรง แน่นอนว่ามีข้อเสีย แต่ Rust เป็นภาษาที่ควรเรียนสักครั้งจริง ๆ และวิธีที่ Rust ใช้ลดข้อผิดพลาดนั้นยังเอาไปเป็นนิสัยการพัฒนาที่ดีในภาษาอื่นได้ด้วย

    • จริงอยู่ที่ Rust ซับซ้อนมาก จน LLM สร้างโค้ด Rust ที่ถูกต้องตั้งแต่ครั้งแรกได้ยาก แต่ผมก็ยังคิดว่ามันดีกว่าปัญหามากมายของ JavaScript หรือภาษา dynamic/weakly typed อื่น ๆ มาก

    • ผมเรียน Rust แล้วและเห็นด้วยกับคุณ Rust ซับซ้อนจริง และเป็นภาษาสไตล์ “ออกแบบโดยคณะกรรมการ” แม้ tooling จะยอดเยี่ยม และมันก็ยังซับซ้อนน้อยกว่า C++ แต่ก็ไม่ใช่ภาษาที่เรียนง่ายเลย

    • ปัญหาของบทความแนวนี้คือมันไม่แตะสาระสำคัญ Rust มีโปรแกรมบางประเภทที่มันไม่ยอมให้เขียนเลย ซึ่งก็มีเหตุผลดีพอสมควร แต่จุดนี้ต่างจากแทบทุกภาษาที่คนส่วนใหญ่เคยใช้มาโดยพื้นฐาน เพราะมีโปรแกรมที่เขียนเป็น Rust ไม่ได้จริง ๆ คุณต้องยอมรับเรื่องนี้ ไม่อย่างนั้น Rust ก็อาจไม่เหมาะกับคุณ

  • หนึ่งในวิธีที่คนไม่ค่อยใช้กันเวลาเรียน Rust คือเริ่มจากเรียนแค่บางส่วนของภาษาก่อน ตัวอย่างเช่น หนังสือสอน Rust ของผมไม่สอน lifetime เลยตั้งแต่แรก เพราะแค่ใช้ฟังก์ชันที่ไม่มี lifetime ก็เขียนโปรแกรมที่ทำงานได้ดีพอมากมายแล้ว macro ก็เช่นกัน แม้จะไม่ง่าย แต่ก็ควรเริ่มจาก subset ก่อน และผมคิดว่าการเริ่มจากแนวคิดเรื่อง borrow ก่อน แทนที่จะพึ่งแต่ copy() หรือ clone() ตั้งแต่ต้น เป็นแนวทางที่ถูกต้องกว่า เพราะ borrow คือแก่นของภาษา

  • วิธีเดียวที่จะทำให้ผมเรียน Rust คือมีงานเงินเดือนเกิน 300,000 ดอลลาร์จำนวนมาก ผมคิดว่า Rust ก็อาจมีศักยภาพแทนที่ C++ ในสาย quant ได้ในอนาคต แต่ตอนนี้ก็มี OCaml อยู่แล้ว และถ้าต้องเรียนภาษาที่ทั้งยากและซับซ้อนมาก ๆ อย่างน้อยก็ควรเห็นเงินก่อน งานที่เงินดีที่สุดที่ผมเคยมีจนถึงตอนนี้คือสาย Python

  • พออ่านคอมเมนต์เหล่านี้ก็ทำให้ตระหนักถึงท่าทีที่มักเห็นในโปรแกรมเมอร์รุ่นเก่าเวลาโดนท้วงติง ยิ่งทำงานนานก็ยิ่งดื้อได้ง่าย ผมอยากให้แต่ละคนลองถามตัวเองดูว่าทำไมถึงต่อต้านคำแนะนำของคอมไพเลอร์ อยากทำอะไรให้ต่างออกไป และมีอะไรเป็นตัวขัดขวางอยู่จริง ๆ