Reputation: 319
I was designing a library that would transliterate given string into English from Ukrainian, so I decided to use 'match' operator for defining statement with check of multiple conditions. But I bumped into compiler error, which is typical to Rust, but fully impossible in my situation(at least I suppose so).
--> src/lib.rs:188:21
|
188 | origin_mutated[i] = 'Y';
| ^^^^^^^^^^^^^^ use of possibly-uninitialized `origin_mutated`
error: aborting due to previous error
Here is full code of a library. Please bump my nose into a problem, if I'm not seeing something obvious(because I have suspicion that it may be a bug in compiler)
pub fn transliterate(mut origin: String) -> String {
let counter: usize = origin.chars().count();
let mut j: usize = 0;
let mut i: usize = 0;
let origin_vec: Vec<char> = origin.chars().collect();
let mut origin_mutated: Vec<char>;
if j <= counter{
while j <= counter {
match origin_vec[j] {
'А' => {
origin_mutated[i] = 'A';
i+=1;
j+=1;
},
'Б' => {
origin_mutated[i] = 'B';
j+=1;
i+=1;
},
'В' => {
origin_mutated[i] = 'V';
i+=1;
j+=1;
},
'Г' => {
origin_mutated[i] = 'H';
i+=1;
j+=1;
},
'Ґ' => {
origin_mutated[i] = 'G';
i+=1;
j+=1;
},
'Д' => {
origin_mutated[i] = 'D';
i+=1;
j+=1;
},
'Е' => {
origin_mutated[i] = 'E';
i+=1;
j+=1;
},
'Є' => {
origin_mutated[i] = 'Y';
i+=1;
j+=1;
origin_mutated[i] = 'e';
i+=1;
},
'Ж' => {
origin_mutated[i] = 'Z';
i+=1;
j+=1;
origin_mutated[i] = 'h';
i+=1;
},
'З' => {
origin_mutated[i] = 'Z';
i+=1;
j+=1;
},
'И' => {
origin_mutated[i] = 'Y';
i+=1;
j+=1;
},
'І' => {
origin_mutated[i] = 'I';
i+=1;
j+=1;
},
'Ї' => {
origin_mutated[i] = 'Y';
i+=1;
j+=1;
origin_mutated[i] = 'i';
i+=1;
},
'Й' => {
origin_mutated[i] = 'Y';
i+=1;
j+=1;
},
'К' => {
origin_mutated[i] = 'K';
i+=1;
j+=1;
},
'Л' => {
origin_mutated[i] = 'L';
i+=1;
j+=1;
},
'М' => {
origin_mutated[i] = 'M';
i+=1;
j+=1;
},
'Н' => {
origin_mutated[i] = 'N';
i+=1;
j+=1;
},
'О' => {
origin_mutated[i] = 'O';
i==1;
j+=1;
},
'П' => {
origin_mutated[i] = 'P';
i+=1;
j+=1;
},
'Р' => {
origin_mutated[i] = 'R';
i==1;
j+=1;
},
'С' => {
origin_mutated[i] = 'S';
i==1;
j+=1;
},
'Т' => {
origin_mutated[i] = 'T';
i==1;
j+=1;
},
'У' => {
origin_mutated[i] = 'U';
i+=1;
j+=1;
},
'Ф' => {
origin_mutated[i] = 'F';
i==1;
j+=1;
},
'Х' => {
origin_mutated[i] = 'K';
i+=1;
j==1;
origin_mutated[i] = 'h';
i+=1;
},
'Ц' => {
origin_mutated[i] = 'T';
i+=1;
j+=1;
origin_mutated[i] = 's';
i+=1;
},
'Ч' => {
origin_mutated[i] = 'C';
i+=1;
j+=1;
origin_mutated[i] = 'h';
i+=1;
},
'Ш' => {
origin_mutated[i] = 'S';
i+=1;
j+=1;
origin_mutated[i] = 'h';
i+=1;
},
'Щ' => {
origin_mutated[i] = 'S';
i+=1;
j==1;
origin_mutated[i] = 'h';
i+=1;
origin_mutated[i] = 'c';
i+=1;
origin_mutated[i] = 'h';
i+=1;
},
'Ю' => {
origin_mutated[i] = 'Y';
i+=1;
j+=1;
origin_mutated[i] = 'u';
i+=1;
},
'Я' => {
origin_mutated[i] = 'Y';
i+=1;
j+=1;
origin_mutated[i] = 'a';
i+=1;
},
_ => {
j+=1;
}
}
}
}
else if j > counter{
origin_mutated[i] = '\n';
}
else {
origin = origin_mutated.into_iter().collect();
}
//origin = origin_mutated.into_iter().collect();
(origin)
}
Upvotes: 5
Views: 4676
Reputation: 13628
All stack variables in Rust are uninitialized until a value is explicitly assigned to them:
let mut origin_mutated: Vec<char>
Here, origin_mutated
is not actually initialized as a vector. It it simply a placeholder for a vector that may or may not be initialized in the future.
Because Rust does not know if the variable was initialized, the compiler statically prevents you from reading it:
|
188 | origin_mutated[i] = 'Y';
| ^^^^^^^^^^^^^^ use of possibly-uninitialized `origin_mutated`
The solution is to initialize origin_mutated
as an empty vector:
let mut origin_mutated: Vec<char> = Vec::new()
Upvotes: 0
Reputation: 6862
The reason for the error is that this line does NOT create a Vec:
let mut origin_mutated: Vec<char>;
It creates a variable which could hold a Vec, but doesn't yet, not even a zero-length one. It's like saying
let a: i32;
It doesn't have a value. You probably meant
let mut origin_mutated: Vec<char> = Vec::new();
Upvotes: 9
Reputation: 451
I'm not sure why your program doesn't compile, but even if it did compile, I think it'd probably panic when you try to index your origin_mutated
vector. The reason is that your origin_mutated
vec has a length of 0, so trying to index into it will panic according to the docs.
You can't index into an element of your vector which doesn't exist yet. You'd need to use a method like push()
or similar to grow your Vec
.
But there's an even better way to do this with Rust: by iterating over the input String
and map
ping over its elements:
pub fn transliterate(origin: &str) -> String {
origin.chars().map(transliterate_letter).collect()
}
fn transliterate_letter(letter: char) -> &'static str {
match letter {
'А' => "A",
'Б' => "B",
...
'Є' => "Ye",
...
}
}
Upvotes: 4