CSC 123/252 Nightmare Test You just found out that the programming languages final is TODAY! You want to panic! but panic! in Rust is bad!. test.map(|x|println!("good luck on {}",x)); 1. (8) Select all true statments: a. Rust does not have exceptions because exceptions are dynamically scoped b. Rust always guarantees tail-recursion optimization c. C++ can still have memory leaks even with the exclusive use of unique_ptr and make_unique (no raw pointers) d. In a Rust expression of the form `n.f()`, dynamic dispatch is always used to determine which function f to call on object n. f. Pattern matching in F# and Rust is equivalent to multiple-dispatch in Julia g. Rust will automatically move values from stack to heap in order to extend their "lifetime", just like the language Go. h. Calling .unwrap on an Option in Rust can result in panic (crash). i. F# is not as strongly type checked at compile time as C# j. Rust can never have a memory leak WARNING: selecting certain items may result in a score of zero regardless of what else was selected. a, c, h are true. Selecting d and/or g will result in 0. 2. In Rust, `std::env::args()` returns an Iterator over the command-line arguments, as owned Strings, passed to main. std::evn::args().nth(1) will give you the first argument, if it exists. It returns an Option. Give a string (or slice) s, `s.parse::()` will attempt to convert the string into an unsiged integer that can be used as a size or index. It will return a Result. For example, "12".parse::() will return Ok(12) and "abc".parse:: will return Err(e) where e is a ParseIntError object (when printed, it will say "error invalid digit found in string"). The following code was written by someone who was terrible at monadic error handling (though it compiles). fn main() { let mut n = 100; // default value of n, can be change by command-line arg let option1 = std::env::args().nth(1); if option1.is_some() { let string1 = option1.unwrap(); let result1 = string1.parse::(); if result1.is_ok() { n = result1.unwrap(); } } // ... } 2a. Rewrite the above using pattern matching. You may not call is_some/is_ok or unwrap/unwrap_or. You may only use match and if-let. if let Some(x) = std::env::args().nth(1) { if let Ok(y) = x.parse::() { n = y; } } 2b. Rewrite the above using only .map and/or .and_then. No more than two calls are allowed (two .map/.and_then) std::env::args().nth(1) .map(|x|{x.parse::() .map(|y|{ n = y; });}); 3. The following function takes a mutable borrow of a vector and returns a vector of mutable borrows of the values of the vector. Explain why it doesn't compile (in your own words) then write a correct version. Do not change the function's type (signature). fn mutborrows(v:&mut Vec) -> Vec<&mut T> { let mut i = 0; let mut mv = Vec::new(); for x in v.iter_mut() { mv.push(x); } /* let vlen = v.len(); while i(10); auto b = make_unique(10); a = move(b); /* int *a = new int[10]; int *b = new int[10]; a = b; delete a; delete b; */ } 6. Give an example of how mixing raw pointers with unique_ptr can compromise the effectiveness of the smart pointer. Write no more than three lines of code in C++. auto a = make_unique(10); auto b = make_unique(10); memcpy(&a,&b,sizeof(unique_ptr)); // #include // copies unique pointer or int x; unique_ptr p(&x); // unique pointer to stack, not heap unique_ptr q(&x); // uniquely not unique 7. You finally wake up and realize that it's only a nightmare. test was None, so test.map(|x|println!("good luck on { }",x)); didn't print anything. Study hard but don't panic! I recommend re-reading the critical notes on memory management in C++ and the transition guide to Rust. All assignments are due before the final exam.