星期一, 1月 01, 2024

Rust 陣列 Option 的初始化

在撰寫一些程式的過程中,需要建立一個 String 的 Array,且陣列元素有可能沒有字串。於是我寫下了以下的 Code。
fn main() {
  let s1: [Option<String>; 26] = [None; 26];
}
在 Rust 中陣列的型別使用 [TYPE; LENGTH],並且可以用 [EXPR; LENGTH] 來進行初始化。 這段程式編譯後會得到以下錯誤。
let s1: [Option<String>; 26] = 
   [None; 26];
    ^^^^ the trait `Copy` is not implemented for `String`
至於原因可以把以上的 Code 展開為
s1[0] = None;
s1[1] = None;
...
s1[25] = None;

因此會要求 [EXPR; LENGTH] 中的 EXPR 需要有 Copy Trait,否則會 Move 導致 s1[1] 以後無法被執行。而 Option<String> 中的 String 無法 Move,因此導致 Option<String> 也無法 Move。

雖然 Option::<String>::None 是不含 String,但 Some, None 都是 enum Option 中的一員,無法通過 Trait Bound 檢查可以理解。但以上的檢查有個意外的繞過方法:使用 const。

fn main() {
	const NONE: Option<String> = None;
	let s1: [Option<String>; 26] = [NONE; 26];
}

const 在 Rust 中表示其值會在編譯期間就決定,而非執行時計算。由於編譯期間就確定 [NONE; 26]中的 None 不可能是 Some,於是檢查就通過了...

在 Rust 中的官方文件有說 [EXPR; LENGTH] 中 Expr 需要符合以下條件之一
  • 有實做 Copy Trait
  • 是 const
如果以後 Rust 編譯器不用 const 關鍵字有發現 None 也是 const 的話,以後就不用寫這麼麻煩了。

沒有留言: