rust有哪些坑?
F001 已經(jīng)提到unsafe和借用所有權天生帶來的問題。除此之外目前還遇到另外幾個讓人不爽的地方,大部分已有RFC提出解決方案,但前途不樂觀。
1. Rust沒有subtype, enum 作為首選類型建模工具又沒有實現(xiàn)Dependent Type,最后要enum套struct,比較丑陋。摘自rustc源碼enum TypeStructure {Bool, // boolReference(Region, Mutability, Type), // &'x T, &'x mut TStruct(DefId, &'tcx Substs), // Foo<..>Enum(DefId, &'tcx Substs), // Foo<..>BareFn(&'tcx BareFnData), // fn(..)...}vs C++typedef TypeStructure *Ty;class TypeStructure { .. };class Bool : public TypeStructure { .. };class Reference : public TypeStructure { .. };class Struct : public TypeStructure { .. };class Enum : public TypeStructure { .. };class BareFn : public TypeStructure { .. };2. 常數(shù)不能作為泛型參數(shù)。所以當結(jié)構包含不定長數(shù)組時,要將這個數(shù)組類型作為一個泛型參數(shù),或傳入數(shù)組引用,破壞了封裝。let mut vector: ArrayDeque = ArrayDeque::new();vslet mut vector: ArrayDeque<8> = ArrayDeque::new();3. 不能棧上分配不定長內(nèi)存。Rust中涉及閉包、trait object、環(huán)形引用的部分強制應用堆分配。在部分實時系統(tǒng)里不能用堆時就比較痛苦了。4. 錯誤處理上偷師Haskell用Option又沒學完,既沒有monad 也沒有 do notation。這里舉Future的例子,option和result同理Rust的Future大概是這樣的。fn main() {let mut core = Core::new().unwrap();let addr = "www.rust-lang.org:443".to_socket_addrs().unwrap().next().unwrap();let socket = TcpStream::connect(&addr, &core.handle());let cx = TlsConnector::builder().unwrap().build().unwrap();let response = socket.and_then(|socket| {cx.connect_async("www.rust-lang.org", socket).map_err(|e| {io::Error::new(io::ErrorKind::Other, e)})}).and_then(|socket| {tokio_core::io::write_all(socket, "\GET / HTTP/1.0\r\n\Host: www.rust-lang.org\r\n\\r\n\".as_bytes())}).and_then(|(socket, _)| {tokio_core::io::read_to_end(socket, Vec::new())});let (_, data) = core.run(response).unwrap();}別人家scala的Future。val usdQuote = Future { connection.getCurrentValue(USD) }val chfQuote = Future { connection.getCurrentValue(CHF) }val purchase = for {usdchfif isProfitable(usd, chf)} yield connection.buy(amount, chf)purchase onSuccess {case _ => println("Purchased " + amount + " CHF")}5. 不支持閉包參數(shù)占位符,也沒有部分應用函數(shù)。combinator寫起來丑陋不說,還比較容易混淆。比如官方文檔說,let letter_count = ['apple', 'banana'].iter().map(|str| { str.len() }).sum();可以改寫為let letter_count = ['apple', 'banana'].iter().map(str::len).sum();但當你豁然貫通之際想要重寫下面這段代碼的時候let at_least_10: Vec<_> = [8, 9, 10, 11].iter().map(|x| { cmp::min(x, 10) }).collect();發(fā)現(xiàn)Rust其實并沒有部分應用函數(shù)。。。let at_least_10: Vec<_> = [8, 9, 10, 11].iter().map(cmp::min(_, 10)).collect(); // 不能編譯再看看隔壁scala的val at_least_10 = List(8, 9, 10, 11).map(_ min 10).reduceLeft(_ + _);6. Trait 沒有字段。這個見仁見智,trait默認實現(xiàn)用到結(jié)構的字段時,目前的標準寫法是,trait定義一個 get_xxx()方法給結(jié)構實現(xiàn),不是那么的高效。我覺得這個feature還是比較重要的,不知為何不在1.0前加入。,core team 早已有人提出, 但也是一直被推遲。7. 最后是一個生命周期設計上的問題——生命周期過早開始和過早結(jié)束,在3年前被核心成員發(fā)現(xiàn)并提出解決方案,但一直推遲到1.0發(fā)布直到今天還沒解決。比方說,下面這段不能編譯let vec = vec![...];vec.remove(vec.len() - 1); // vec已被借用原因是第二句被展開為Vec::remove(&mut vec, vec.len() - 1); // 第一個參數(shù)傳遞可變借用,第二個參數(shù)時就不能再借出了一定要寫成let vec = vec![...];let len = vec.len();vec.remove(len - 1);