diff --git a/Discussion/08 Common Collections/HashMap_practice.rs b/Discussion/08 Common Collections/HashMap_practice.rs new file mode 100644 index 0000000..950c8ae --- /dev/null +++ b/Discussion/08 Common Collections/HashMap_practice.rs @@ -0,0 +1,154 @@ +// Ch.8 Hash Map + +// HashMap +// This is similar to C++'s "map" and Python's "dictionary". + +// The following code is essential. +use std::collections::HashMap; + +// Creating a new Hash Map +/* +fn main() { + let a: HashMap<&str, i32> = HashMap::new(); // It requires Key's type and Value's type. +} +*/ + +// Recall creating a new vector. +// The followings are wrong. +// The compiler cannot determine the type of Key and Value. +/* +fn main() { + let mut a = HashMap::new(); + let b: HashMap<_, _> = HashMap::new(); +} +*/ + +// Inserting values in a Hash Map +/* +fn main() { + // (1) Use insert. + let mut a = HashMap::new(); + a.insert("SCSC", 438); // The compiler can determine the type of Key and Value. + + let mut b: HashMap<_, _> = HashMap::new(); + b.insert(438, "SCSC"); + + // (2) Use "zip" method and "collect" method. + // "zip" generates a vector of tuples. + // "collect" converts gathered data into various types of collections. + let name = vec!["SCSC", "내마음"]; + let num = vec![438, 437]; + let 동아리방: HashMap<_, _> = name.iter().zip(num.iter()).collect(); +} +*/ + +// Accessing values in a Hash Map +// (1) "get" method +/* +fn main() { + let mut ten = HashMap::new(); + ten.insert(1, 10); + ten.insert(2, 20); + + let b = 1; + let b10 = ten.get(&b); // The type of b10 is Option<&i32>. b10 is equal to Some(&10). + + let c = 3; + let c10 = ten.get(&c); // c10 is equal to None. 3 is an invalid key. + + // We want to use i32. + // (i) Option<&i32> -> Option by "copied" method. + // (ii) Option -> i32 by "unwrap" method. + let d = 2; + let d10 = ten.get(&d).copied().unwrap(); + println!("{}", d10); + + // None -> i32 by "unwrap_or" method. + let e = 5; + let e10 = ten.get(&e).copied().unwrap_or(0); + println!("{}", e10); +} +*/ + +// (2) Iteration +/* +fn main() { + let mut ten = HashMap::new(); + ten.insert(1, 10); + ten.insert(2, 20); + + for (key, value) in &ten { + println!("{}: {}", key, value); + } + for (key, value) in ten { // In this case, the ownership of ten is moved. + println!("{}: {}", key, value); + } + // ten is unavailable. + /* + for (key, value) in &ten { + println!("{}: {}", key, value); + } + */ +} +*/ + +// Hash Maps and Ownership +/* +fn main() { + let mut a = HashMap::new(); + let x = String::from("아디오스"); + let y = String::from("베이비"); + println!("끝이다. 유언을 남겨라.\n{} {}...", x, y); + + a.insert(x, y); // x, y are moved into a. + // println!("끝이다. 유언을 남겨라.\n{} {}...", x, y); // x, y is unavailable. +} +*/ + +// Updating a Hash Map +// Overwriting a value. One key should have one value. +/* +fn main() { + let mut a = HashMap::new(); + a.insert(1, 10); + a.insert(2, 20); + a.insert(1, 100); // Overwriting. + println!("{:?}", a); // This format outputs all {key : value} in a Hash Map. +} +*/ + +// Adding a Key and Value only iff a Key does not exist. +// "entry" method for Hash Map and "or_insert" method for Entry +/* +fn main() { + let mut a = HashMap::new(); + a.insert(1, 10); + a.insert(2, 20); + + a.entry(1).or_insert(100); + a.entry(3).or_insert(30); + println!("{:?}", a); +} +// There is one observation that can be made through println!("{:?}", a);. +// In Rust, a HashMap does not guarantee a specific order for its entries. +// It is similar to the dictionary in older versions of Python. +*/ + +// Updating a value based on the old value +// We utilize the fact that "entry" method returns a reference to the Entry if the key exists. +// "or_insert" method returns a reference to the value of the Entry. +/* +fn main() { + let mut a = HashMap::new(); + a.insert(1, 10); + a.insert(2, 20); + a.insert(3, 30); + + for i in 1..4 { + // let val = a.entry(i); // Modifying an Entry is not allowed. + let val = a.entry(i).or_insert(0); + *val *= 10; + } + println!("{:?}", a); +} +*/ diff --git a/Discussion/08 Common Collections/HashMap_read.rs b/Discussion/08 Common Collections/HashMap_read.rs new file mode 100644 index 0000000..f9c9c78 --- /dev/null +++ b/Discussion/08 Common Collections/HashMap_read.rs @@ -0,0 +1,136 @@ +// Ch.8 Hash Map + +// HashMap +// This is similar to C++'s "map" and Python's "dictionary". + +// The following code is essential. +use std::collections::HashMap; + +// Creating a new Hash Map +fn main() { + let a: HashMap<&str, i32> = HashMap::new(); // It requires Key's type and Value's type. +} + +// Recall creating a new vector. +// The followings are wrong. +// The compiler cannot determine the type of Key and Value. +fn main() { + let mut a = HashMap::new(); + let b: HashMap<_, _> = HashMap::new(); +} + +// Inserting values in a Hash Map +fn main() { + // (1) Use insert. + let mut a = HashMap::new(); + a.insert("SCSC", 438); // The compiler can determine the type of Key and Value. + + let mut b: HashMap<_, _> = HashMap::new(); + b.insert(438, "SCSC"); + + // (2) Use "zip" method and "collect" method. + // "zip" generates a vector of tuples. + // "collect" converts gathered data into various types of collections. + let name = vec!["SCSC", "내마음"]; + let num = vec![438, 437]; + let 동아리방: HashMap<_, _> = name.iter().zip(num.iter()).collect(); +} + +// Accessing values in a Hash Map +// (1) "get" method +fn main() { + let mut ten = HashMap::new(); + ten.insert(1, 10); + ten.insert(2, 20); + + let b = 1; + let b10 = ten.get(&b); // The type of b10 is Option<&i32>. b10 is equal to Some(&10). + + let c = 3; + let c10 = ten.get(&c); // c10 is equal to None. 3 is an invalid key. + + // We want to use i32. + // (i) Option<&i32> -> Option by "copied" method. + // (ii) Option -> i32 by "unwrap" method. + let d = 2; + let d10 = ten.get(&d).copied().unwrap(); + println!("{}", d10); + + // None -> i32 by "unwrap_or" method. + let e = 5; + let e10 = ten.get(&e).copied().unwrap_or(0); + println!("{}", e10); +} + +// (2) Iteration +fn main() { + let mut ten = HashMap::new(); + ten.insert(1, 10); + ten.insert(2, 20); + + for (key, value) in &ten { + println!("{}: {}", key, value); + } + for (key, value) in ten { // In this case, the ownership of ten is moved. + println!("{}: {}", key, value); + } + // ten is unavailable. + /* + for (key, value) in &ten { + println!("{}: {}", key, value); + } + */ +} + +// Hash Maps and Ownership +fn main() { + let mut a = HashMap::new(); + let x = String::from("아디오스"); + let y = String::from("베이비"); + println!("끝이다. 유언을 남겨라.\n{} {}...", x, y); + + a.insert(x, y); // x, y are moved into a. + // println!("끝이다. 유언을 남겨라.\n{} {}...", x, y); // x, y is unavailable. +} + +// Updating a Hash Map +// Overwriting a value. One key should have one value. +fn main() { + let mut a = HashMap::new(); + a.insert(1, 10); + a.insert(2, 20); + a.insert(1, 100); // Overwriting. + println!("{:?}", a); // This format outputs all {key : value} in a Hash Map. +} + +// Adding a Key and Value only iff a Key does not exist. +// "entry" method for Hash Map and "or_insert" method for Entry +fn main() { + let mut a = HashMap::new(); + a.insert(1, 10); + a.insert(2, 20); + + a.entry(1).or_insert(100); + a.entry(3).or_insert(30); + println!("{:?}", a); +} +// There is one observation that can be made through println!("{:?}", a);. +// In Rust, a HashMap does not guarantee a specific order for its entries. +// It is similar to the dictionary in older versions of Python. + +// Updating a value based on the old value +// We utilize the fact that "entry" method returns a reference to the Entry if the key exists. +// "or_insert" method returns a reference to the value of the Entry. +fn main() { + let mut a = HashMap::new(); + a.insert(1, 10); + a.insert(2, 20); + a.insert(3, 30); + + for i in 1..4 { + // let val = a.entry(i); // Modifying an Entry is not allowed. + let val = a.entry(i).or_insert(0); + *val *= 10; + } + println!("{:?}", a); +} diff --git a/Discussion/08 Common Collections/String_practice.rs b/Discussion/08 Common Collections/String_practice.rs new file mode 100644 index 0000000..cec98b6 --- /dev/null +++ b/Discussion/08 Common Collections/String_practice.rs @@ -0,0 +1,109 @@ +// Ch.8 String + +// String is mutable. +// String has an ownership. +// String is encoded in UTF-8. +// Note that "str" and "String" are different. + +// Creating a new String. +// Emtpy String. +/* +fn main() { + let s = String::new(); // But, immutable empty String is useless. + let mut s = String::new(); +} +*/ + +// String with an inital value. +/* +fn main() { + let data = "init"; + let s = data.to_string(); + let s = "init".to_string(); + let s = String::from("init"); +} +*/ + +// Updating a String +// Appending with "push_str" and "push" +/* +fn main() { + let mut s = String::from("S"); + s.push_str("C"); // The type of "C" is &str. + + let s2 = "S"; + s.push_str(s2); // The type of s2 is &str. + s.push_str(&s2); // Note that &s2 is also of type &str. + println!("s2 is {}", s2); + + s.push('C'); // The type of 'C' is char. + println!("{}", s); + + let s3: char = '!'; + s.push(s3); + println!("{}", s); // "push" requires a char argument. +} +*/ + +// Concatenation +// (1) "+" Operation +/* +fn main() { + let s1 = String::from("SC"); + let s2 = String::from("SC"); + let s3 = s1 + &s2; // s1 becomes unavailable. +} +*/ + +// The implementation of "+" for a String. +// fn add(self, s: &str) -> String +// The first term: self - It does not have &. +// The second term: s: &str - It has &. +/* +fn main() { + let s1 = String::from("1"); + let s2 = String::from("2"); + let s3 = String::from("3"); + let s = s1 + "+" + &s2 + "+" + &s3; // In this case, using "+" is too complex. + println!("{}", s); + + // (2) "format!" macro + let s1 = String::from("응애"); // We need new s1 based on the above result. + let so_gorgeous_s = format!("{}+{}+{}", s1, s2, s3); + println!("{}", so_gorgeous_s); + println!("아앗 너는 s1? {}", s1); // Macro uses references. +} +*/ + +// Indexing into Strings +// The following code will produce an error. +/* +fn main() { + let s = String::from("Hi"); + let a = s[0]; // String cannot be indexed by an integer. +} +*/ +// An index into the String’s bytes will not always correlate to a valid Unicode scalar value. + +// Three ways to look at Strings from Rust’s perspective +// (1) Byte (2) Scalar value (= char) (3) Grapheme cluster + +// Slicing Strings +/* +fn main() { + let s = String::from("Hi"); + let a = &s[0..2]; // We must use &. + // let a = s[0..2]; // It occurs an error. + println!("{}", a); + + let b = &s[0..1]; + println!("{}", b); // This slicing works just like indexing. + + // Slicing the String based on bytes. + let k = String::from("한국말"); + let c = &k[0..3]; // "한" occupies 3 bytes. + // let d = &k[0..2]; + // let e = &k[0..7]; // They occur errors. + println!("{}", c); +} +*/ diff --git a/Discussion/08 Common Collections/String_read.rs b/Discussion/08 Common Collections/String_read.rs new file mode 100644 index 0000000..dc39623 --- /dev/null +++ b/Discussion/08 Common Collections/String_read.rs @@ -0,0 +1,95 @@ +// Ch.8 String + +// String is mutable. +// String has an ownership. +// String is encoded in UTF-8. +// Note that "str" and "String" are different. + +// Creating a new String. +// Emtpy String. +fn main() { + let s = String::new(); // But, immutable empty String is useless. + let mut s = String::new(); +} + +// String with an inital value. +fn main() { + let data = "init"; + let s = data.to_string(); + let s = "init".to_string(); + let s = String::from("init"); +} + +// Updating a String +// Appending with "push_str" and "push" +fn main() { + let mut s = String::from("S"); + s.push_str("C"); // The type of "C" is &str. + + let s2 = "S"; + s.push_str(s2); // The type of s2 is &str. + s.push_str(&s2); // Note that &s2 is also of type &str. + println!("s2 is {}", s2); + + s.push('C'); // The type of 'C' is char. + println!("{}", s); + + let s3: char = '!'; + s.push(s3); + println!("{}", s); // "push" requires a char argument. +} + +// Concatenation +// (1) "+" Operation +fn main() { + let s1 = String::from("SC"); + let s2 = String::from("SC"); + let s3 = s1 + &s2; // s1 becomes unavailable. +} + +// The implementation of "+" for a String. +// fn add(self, s: &str) -> String +// The first term: self - It does not have &. +// The second term: s: &str - It has &. +fn main() { + let s1 = String::from("1"); + let s2 = String::from("2"); + let s3 = String::from("3"); + let s = s1 + "+" + &s2 + "+" + &s3; // In this case, using "+" is too complex. + println!("{}", s); + + // (2) "format!" macro + let s1 = String::from("응애"); // We need new s1 based on the above result. + let so_gorgeous_s = format!("{}+{}+{}", s1, s2, s3); + println!("{}", so_gorgeous_s); + println!("아앗 너는 s1? {}", s1); // Macro uses references. +} + +// Indexing into Strings +// The following code will produce an error. +fn main() { + let s = String::from("Hi"); + let a = s[0]; // String cannot be indexed by an integer. +} +// An index into the String’s bytes will not always correlate to a valid Unicode scalar value. + +// Three ways to look at Strings from Rust’s perspective +// (1) Byte (2) Scalar value (= char) (3) Grapheme cluster + +// Slicing Strings +fn main() { + let s = String::from("Hi"); + let a = &s[0..2]; // We must use &. + // let a = s[0..2]; // It occurs an error. + println!("{}", a); + + let b = &s[0..1]; + println!("{}", b); // This slicing works just like indexing. + + // Slicing the String based on bytes. + let k = String::from("한국말"); + let c = &k[0..3]; // "한" occupies 3 bytes. + // let d = &k[0..2]; + // let e = &k[0..7]; // They occur errors. + println!("{}", c); +} diff --git a/Discussion/08 Common Collections/Vector_practice.rs b/Discussion/08 Common Collections/Vector_practice.rs new file mode 100644 index 0000000..8a3ce3b --- /dev/null +++ b/Discussion/08 Common Collections/Vector_practice.rs @@ -0,0 +1,211 @@ +// Ch.8 Vector + +// Creating a new vector +// (1) Use Vec::new function +/* +fn main() { + // let v: Vec = Vec::new(); + let v: Vec = Vec::new(); + let v: Vec = Vec::new(); + let v: Vec<&str> = Vec::new(); + let v: Vec = Vec::new(); +} +*/ + +// If we don't specify the type of the vector, we should use "mut". +// The following code will produce an error. +/* +fn main() { + let v = Vec::new(); +} +*/ + +// Unfortunately, the following code will also produce an error. +/* +fn main() { + let mut v = Vec::new(); +} +*/ + +// The reason is still that the compiler cannot determine the type of the vector's elements. +// Therefore, by inserting elements as follows, no error occurs. +/* +fn main() { + let mut v = Vec::new(); + v.push(1); + // v.push("Hello"); +} +*/ + +// (2) Use vec! method +/* +fn main() { + let v = vec!["응", "애"]; + // let v = vec![1, 2, 3, 4]; +} +*/ + +// Updating a vector +// We can update a vector by using push method. Do not forget to use "mut". +/* +fn main() { + let mut v: Vec<&str> = Vec::new(); + v.push("응"); + v.push("애"); + let mut v = Vec::new(); + v.push("응"); + v.push("뀨"); +} +*/ + +// Reading elements of a vector +// There are two ways. (1) Use index. (2) Use get method. +/* +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let first: i32 = v[0]; + let second: &i32 = &v[1]; + let third: Option = Some(v[2]); // We must use "Some". + let fourth: Option<&i32> = Some(&v[3]); + let fifth: Option<&i32> = v.get(4); // We must not use "Some". + + // The following codes will produce errors. + // let third: Option = v[2]; // v[2] is i32. + // let fourth: Option<&i32> = Some(v[3]); // We need &. + // let fifth: Option<&i32> = Some(v.get(4)); // v.get(4) is already Option<&i32>. + // let fifth: &i32 = v.get(4); +} +*/ + +// Out of range +/* +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let a = v.get(100); + // get method returns a value of type Option<&T>. So a is None. + + // The following code will produce an error. + // let a = v[100]; + // This is not a compile error. This is a runtime error. This causes "panic!". +} +*/ + +// Invalid reference +/* +fn main() { + let mut v = vec![1]; + let a = &v[0]; + v.push(3); + + // If we don't use the variable "a", no error occurs. + // By adding the following code, the same error as described in the book occurs. + // println!("{}", a); +} +*/ + +// Consider the ownership when Strings are in a vector. +/* +fn I_will_steal_your_ownership(s: String) { + println!("빼앗았다. {}", s); +} +fn I_dont_need_your_ownership(s: &String) { + println!("너의 소유권은 필요 없었다. {}", s); +} +fn main() { + // let v = vec!["뀨잉..."] // In this case, the type of "뀨잉..." is &str. + let v = vec![String::from("뀨잉...")]; // To use String, we must use String::from or to_string. + let s = String::from("r"); + I_dont_need_your_ownership(&v[0]); + println!("{}", v[0]); + + // The following code will produce an error. + // I_will_steal_your_ownership(v[0]); + // We cannot move the ownership of an element inside a vector. +} +*/ + +// Iterating over the values in a vector. +/* +fn main() { + let v = vec![1, 2, 3, 4, 5]; + /* + for i in v { // Impossible. We need &. + println!("{}", i); + } + */ + // Using reference. + for i in &v { + println!("{}", i); + } + + /* + for i in &mut v { // Impossible. Note that v is immutable. + *i += 5; + println!("{}", i); + } + */ + let mut v = vec![1, 2, 3, 4, 5]; + for i in &mut v { // Now, it is possible. + *i += 5; + println!("{}", i); + } + + // Using iterator. + for i in v.iter() { + println!("{}", i); + } + for i in v.iter().rev() { + println!("{}", i); + } + + // Using index. + for i in 0..5 { + println!("{}", v[i]); + } + for i in (0..5).rev() { + println!("{}", &v[i]); + } + /* + for i in 0.. { // It occur "panic!" since the size of v is 5. + println!("{}", v[i]); + } + */ +} +*/ + +// Using an enum to store multiple types +/* +enum Info { + CodeName(char), + Age(i32), + Ability(String) +} +fn main() { + // We can store values of multiple types in a vector. + // Actually, to be precise, they are all of the type Info. + let info1 = vec![ + Info::CodeName('S'), + Info::Age(24), + Info::Ability(String::from("바람과 함께 사라지기")) + ]; + + let mut info2: Vec = Vec::new(); + info2.push(Info::Age(24)); +} +*/ + +// When a vector goes out of scope, both the vector and its elements are dropped. +/* +fn main() { + let mut ans = "쀼"; + { + let v = vec!["구", "뀨"]; + println!("비둘기가 두 번 울면?\n답: {}", v[1]); + ans = &v[1]; + } + // The following code will produce an error. + // println!("비둘기가 두 번 울면?\n답: {}", v[1]); + // But, the code below is fine. + println!("비둘기가 두 번 울면?\n답: {}", ans); +} +*/ diff --git a/Discussion/08 Common Collections/Vector_read.rs b/Discussion/08 Common Collections/Vector_read.rs new file mode 100644 index 0000000..d58a667 --- /dev/null +++ b/Discussion/08 Common Collections/Vector_read.rs @@ -0,0 +1,185 @@ +// Ch.8 Vector + +// Creating a new vector +// (1) Use Vec::new function +fn main() { + // let v: Vec = Vec::new(); + let v: Vec = Vec::new(); + let v: Vec = Vec::new(); + let v: Vec<&str> = Vec::new(); + let v: Vec = Vec::new(); +} + +// If we don't specify the type of the vector, we should use "mut". +// The following code will produce an error. +fn main() { + let v = Vec::new(); +} + +// Unfortunately, the following code will also produce an error. +fn main() { + let mut v = Vec::new(); +} + +// The reason is still that the compiler cannot determine the type of the vector's elements. +// Therefore, by inserting elements as follows, no error occurs. +fn main() { + let mut v = Vec::new(); + v.push(1); + // v.push("Hello"); +} + +// (2) Use vec! method +fn main() { + let v = vec!["응", "애"]; + // let v = vec![1, 2, 3, 4]; +} + +// Updating a vector +// We can update a vector by using push method. Do not forget to use "mut". +fn main() { + let mut v: Vec<&str> = Vec::new(); + v.push("응"); + v.push("애"); + let mut v = Vec::new(); + v.push("응"); + v.push("뀨"); +} + +// Reading elements of a vector +// There are two ways. (1) Use index. (2) Use get method. +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let first: i32 = v[0]; + let second: &i32 = &v[1]; + let third: Option = Some(v[2]); // We must use "Some". + let fourth: Option<&i32> = Some(&v[3]); + let fifth: Option<&i32> = v.get(4); // We must not use "Some". + + // The following codes will produce errors. + // let third: Option = v[2]; // v[2] is i32. + // let fourth: Option<&i32> = Some(v[3]); // We need &. + // let fifth: Option<&i32> = Some(v.get(4)); // v.get(4) is already Option<&i32>. + // let fifth: &i32 = v.get(4); +} + +// Out of range +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let a = v.get(100); + // get method returns a value of type Option<&T>. So a is None. + + // The following code will produce an error. + // let a = v[100]; + // This is not a compile error. This is a runtime error. This causes "panic!". +} + +// Invalid reference +fn main() { + let mut v = vec![1]; + let a = &v[0]; + v.push(3); + + // If we don't use the variable "a", no error occurs. + // By adding the following code, the same error as described in the book occurs. + // println!("{}", a); +} + +// Consider the ownership when Strings are in a vector. +fn I_will_steal_your_ownership(s: String) { + println!("빼앗았다. {}", s); +} +fn I_dont_need_your_ownership(s: &String) { + println!("너의 소유권은 필요 없었다. {}", s); +} +fn main() { + // let v = vec!["뀨잉..."] // In this case, the type of "뀨잉..." is &str. + let v = vec![String::from("뀨잉...")]; // To use String, we must use String::from or to_string. + let s = String::from("r"); + I_dont_need_your_ownership(&v[0]); + println!("{}", v[0]); + + // The following code will produce an error. + // I_will_steal_your_ownership(v[0]); + // We cannot move the ownership of an element inside a vector. +} + +// Iterating over the values in a vector. +fn main() { + let v = vec![1, 2, 3, 4, 5]; + /* + for i in v { // Impossible. We need &. + println!("{}", i); + } + */ + // Using reference. + for i in &v { + println!("{}", i); + } + + /* + for i in &mut v { // Impossible. Note that v is immutable. + *i += 5; + println!("{}", i); + } + */ + let mut v = vec![1, 2, 3, 4, 5]; + for i in &mut v { // Now, it is possible. + *i += 5; + println!("{}", i); + } + + // Using iterator. + for i in v.iter() { + println!("{}", i); + } + for i in v.iter().rev() { + println!("{}", i); + } + + // Using index. + for i in 0..5 { + println!("{}", v[i]); + } + for i in (0..5).rev() { + println!("{}", &v[i]); + } + /* + for i in 0.. { // It occur "panic!" since the size of v is 5. + println!("{}", v[i]); + } + */ +} + +// Using an enum to store multiple types +enum Info { + CodeName(char), + Age(i32), + Ability(String) +} +fn main() { + // We can store values of multiple types in a vector. + // Actually, to be precise, they are all of the type Info. + let info1 = vec![ + Info::CodeName('S'), + Info::Age(24), + Info::Ability(String::from("바람과 함께 사라지기")) + ]; + + let mut info2: Vec = Vec::new(); + info2.push(Info::Age(24)); +} + +// When a vector goes out of scope, both the vector and its elements are dropped. +fn main() { + let mut ans = "쀼"; + { + let v = vec!["구", "뀨"]; + println!("비둘기가 두 번 울면?\n답: {}", v[1]); + ans = &v[1]; + } + // The following code will produce an error. + // println!("비둘기가 두 번 울면?\n답: {}", v[1]); + // But, the code below is fine. + println!("비둘기가 두 번 울면?\n답: {}", ans); +}