2016年4月21日 星期四

淺談rust option type

強者我同學qcl 做了一系列的簽名檔,大體的概念就是用女友狂炸執行緒,以下是C++ version:
int main(int argc, char *argv[]) {
  QCL *qcl = new QCL();
  Girl *gf = qcl->findGirlfriend();
  printf(“%s\n”, gf→name());
  return 0;
}
qcl@QCLS:~$ g++ qcl.cc
qcl@QCLS:~$ ./a.out
Segmentation fault

另外還有許多版本:python, java, objective C(太強啦都會寫objective C)等等
最近心血來潮寫了一個rust version ,發現正好可以藉此說明option type 的概念,這樣的設計見諸於一些較新的語言,和較舊語言的新標準,如java ver 8和C++,rust 版本如下:
fn main() {
  let qcl = QCL{};
  let gf = qcl.findGirlfriend();
  println!(“{}”, gf.unwrap().name());
}
qcl@QCLS:~$ rustc qcl.rs
qcl@QCLS:~$ ./qcl
thread '<main>' panicked

上面的code 裡,QCL struct 的 findGirlfriend()的宣告如下,它回傳的不是如C++中的Girl,而是Option<Girl>:
fn findGirlfriend(&self) -> Option<Girl>
所謂option type 是用在函式回傳值可能不會回傳東西的時候,包含了兩種可能的變體:Some或None,其基本定義:
pub enum Option<T> {
  None,
  Some(T),
}

例如文中出現的getGirlfriend,亦或在dictionary 查詢的getValue()
若是some 則可存取其中的內容;None 則類似null 的設計,如上例中用unwrap()強行取用內容會造成執行緒崩潰

在上例中,遇到option,比較正規的寫法應該是:
match gf {
  Some(girl) => println!("{}", girl.name()),
  None => println!("Not found"),
}
藉此迴避None 把thread 給炸了,直接unwrap相對在C/C++ version 就是沒去比較return 的pointer == NULL或在python 裡面沒寫 is None,亦或是Golang 裡面沒寫err != nil。

的確,加上match去辨識回傳值是否為None,就跟用了== NULL或is None看似相差無幾,但這裡有個至關緊要的差異,option type 就是option type ,None 只會出現在這裡,若girlfriend 回傳值不是option ,就一定要回傳一個Girl 的實體,不管存取它的name 之後是<林志玲>還是<qcl的右手>,它就必須是一個Girl,儘管解出來是<qcl的右手>它仍然夠格當一位適當的女友。

在其他語言中的Null則不然,我們看到C++ 回傳了一個Null pointer,Null 是空的東西,它什麼都不是;但他被視為Girl pointer,因此我們可以存取它的name,它可以被賦值給任何一種pointer,它又什麼都是,Null 如同變形蟲一樣通過對Girl 的型別檢查,這樣簡單的例外設計有極高的自由,卻也容易出錯。

使用option 讓設計師知道girlfriend有可能為None,也無法對option type 使用來自Girl 的函式與資料,編譯器能在編譯時清楚的指出這類錯誤,並強制設計師在編寫時使用match 檢查,從而避免None 在執行緒中四處散佈,並到了執行時才將執行緒炸掉,如上文中都已經知道可能是None了,又強行unwrap 程式會爆是自己活該。

如果我們用上面的例子寫個比喻:
C語言和允許Null 的語言大概就像:你女友的名字呀,拿去;噢qcl你沒女友呀…干我屁事!你還是自盡吧你
使用Option 的語言會比較貼心一點:女友的名字嗎,嘿qcl 呀,你有可能沒有女友噢,最好處理一下

有關rust 裡option 的相關文件:
https://doc.rust-lang.org/std/option/
https://en.wikipedia.org/wiki/Option_type

關於Null 的一些延伸閱讀:
https://linux.cn/article-6503-1.html
http://openhome.cc/Gossip/Programmer/Null.html

沒有留言:

張貼留言