เรื่องใส่ id สลับที่กัน

เขียน #rustlang แบบ

(word_id, textunit_id) 

วันเดียวพอจำได้หรอก เขียนไปนาน ๆ อาจจะพลาดใส่

(textunit_id, word_id)

ก็ได้

อันนี้ static type อาจจะวืดเพราะทั้ง textunit-id และ word-id ก็เป็น u32 ทั้งคู่ อาจจะแก้แบบนี้สร้าง type มาใหม่เลย WordId กับ TextunitId แต่มันก็เหนื่อยอยู่นะ

ไม่ก็ใช้ struct แทน เช่น

struct WordIdTextunitId {
    word_id: u32,
    textunit_id: u32,
}

อันนี้เขียนง่ายดี แต่ compiler ไม่ได้ช่วยอะไรมากนะ ก็คือ programmer ก็ดูเอาเมื่อไหร่เขียน

WordIdTextunitId { word_id: textunit_id, textunit_id: word_id }

แบบนี้ก็ผิด โปรแกรมเมอร์เห็นเอง แต่ใส่สลับกัน compiler มันก็ผ่านนะ

แล้วคิดไปติดมามันก็พอกับเขียน Clojure เลย

{:word-id word-id
 :textunit-id textunit-id}

แบบนี้ก็ชัดเจนอยู่แล้ว ไม่ต้องประกาศ struct ด้วย หรือจะใช้ defstruct เลยก็ได้

ใน Common Lisp ก็คล้าย ๆ กัน def struct ก็ได้ จะทำเป็น alist ก็ได้

(list (cons :word-id word-id) 
       (cons :textunit-id textunit-id))

แบบนี้ก็ได้

กลับมา Rust จะจัดหนักแบบ ทำแบบนี้ก็บึ้มอยู่ดี

type WordId = u32;
type TextunitId = u32;

struct WordIdTextUnitId {
    word_id: WordId,
    textunit_id: TextunitId,
}

fn main() {
   let w: WordId = 1;
   let t: TextunitId = 2;
   let x = WordIdTextUnitId { word_id: t, textunit_id: w};
}

สลับได้ compiler ไม่ช่วยอะไร

แต่ถ้าทำเป็น struct หมดเลย

struct WordId(u32);
struct TextunitId(u32);

struct WordIdTextUnitId {
    word_id: WordId,
    textunit_id: TextunitId,
}

fn main() {
    let w = WordId(1);
    let t = TextunitId(2);
    let x = WordIdTextUnitId { word_id: t, textunit_id: w};
}

แบบนี้ compiler มันจะช่วยได้รู้แล้วว่าสลับกัน

แต่ก็จะมาเจอว่าผมอยากได้

let v = w + 1; 

แบบนี้ทำไง ก็มีวิธีทำหลายทางนะ เพียงแต่มันก็ต้องออกแรง