###
CSC 123/252 Final Exam, Fall 2021
    There are 100 points possible, with 10 free points. _______ 1. (6) Explain why the following Rust function **will** or **will not** compile: ``` fn f(v:&mut Vec) { v[0] = v[v.len()-1]; } ``` 2. (6) Explain the behavior of the following Rust program: will it compile, and if so, will there be a runtime error or some other behavior. ``` fn main() { let mut v = vec![2,4,5,6]; for x in &v { v.push(*x); } } ``` 3. (6) Explain the behavior of the following C# program: will it compile, give runtime error, or have some other behavior: ``` using System.Collections.Generic; // for List (vector) class public class goodquestion { public static void Main() { List v = new List(); v.Add(123); v.Add("abc"); }//main } ``` 4. (8) The following Rust function *tries* to return a vector containing immutable borrows of all values in both vectors A and B (it's ok to have duplicates in the union). First, explain why the function won't compile, and secondly, show how to write it correctly. Do not change the generic type T (it cannot be assumed to implement any traits). ``` fn union(A:&Vec, B:&Vec) -> Vec<&T> { let mut U:Vec<&T> = Vec::new(); for x in A { U.push(x); } //note: x is inferred to be of type &T for x in B { U.push(x); } return U; } ``` 5. (10) Write a Rust function that reverses in-place a vector of generic values (`Vec`) with no assumptions about T. The function should behave as follows: ``` let mut v = vec![1,2,3]; let mut w = vec!['"a","b","c"]; reverse(&mut v); reverse(&mut w); for x in &v {print!("{} ",x);} // should print 3 2 1 for x in &w {print!("{} ",x);} // should print c b a ``` To write a function over a generic type, use `fn reverse( ...` ``` ``` 6. (14) Consider the following C++ program: ``` #include using namespace std; int* f(int* x) { int* y = new int[2]; y[0] = x[0]+1; y[1] = x[1]+1; return y; } int main() { int* m = new int[2]; m[0] = m[1] = 1; m = f(m); delete(m); cout << "look ma, it compiles!\n"; //what would mother say? return 0; }//main ``` a. Explain why the program contains an error even though it compiles and runs. PINPOINT the exact line(s) where the error occurs. ``` ``` b. Fix the error, either by using `std::unique_ptr` (you must use `unique_ptr`) or rewrite the program in Rust using `Vec` for `int*`. Your program must otherwise emulate the original program as closely as possible. In Rust, function f should be of type `fn(x:Vec) -> Vec` ``` ``` 7. (6) Explain the differences between C++ `shared_ptr` and `weak_ptr`. What are `weak_ptr`? Describe a situation where you would need them. ``` ``` 8. (14) The following defines a simple expression tree in F# ``` type expr = Val of int | Plus of expr*expr | Times of expr*expr;; // function to evaluate expression: let rec eval exp = match exp with | Val(x) -> x | Plus(left,right) -> (eval left) + (eval right) | Times(left,right) -> (eval left) * (eval right);; // function to calculate size of tree: let rec size tree = match tree with | Val(_) -> 1 | Plus(l,r) | Times(l,r)-> (size l) + (size r) let tree1 = Plus(Val(2),Times(Val(4),Val(3))); printfn "%A" (eval tree1) // prints 14 printfn "%A" (size tree1) // prints 3 ``` a. Explain why, in the printfn statements, `(eval tree1)` must have parentheses around it: what would happen without the ()s and **WHY**? That is, can you write it as `printfn "%A" eval(tree1)`? ``` ``` b. Write a function 'find' to determine if an integer x is one of the leaf nodes (`Val(x)`) of a tree. For example, `printfn "%A" (find 4 tree1)` should return true whereas `printfn "%A" (find 7 tree1)` should return false. The space below is more than enough. ``` ``` 9. (10) Compare the above F# program with the following C# program for expression trees: ``` public interface expr { int eval(); int size(); } public class Val : expr { public int x; public Val(int y) {x=y;} public int eval() {return x;} public int size() => 1; // same as {return 1;} } public class Node {// common superclass for Plus, Times public expr left, right; public Plus(expr l, expr r) {left=l; right=r;} public int size() => 1 + left.size()+right.size(); } public class Plus : Node, expr { public Plus(expr l, expr r): base(l,r) {} public int eval() => left.eval() + right.eval(); } public class Times : Node, expr { public Times(expr l, expr r): base(l,r) {} public int eval() => left.eval() * right.eval(); } ``` a. Describe a specific advantage of the F# program over the C# program. That is, describe a situation, with respect to expression trees, where you would use one language instead of the other. Do not describe any general differences between the languages (don't just say that it's "shorter" or "more type safe"). ``` ``` b. Describe an advantage of the C# program over the F# program (please don't say you're more used to the syntax - it's not about you at all). Again, the advantage must be specifically about expression trees and not general differences between the languages. ``` ``` c. Do you know of a way that would be better than both the F# and the C# program, with respect to the tradeoffs of the previous questions, for implementing expression trees? Why is it better? (hint: it's not Rust, but there are at least two correct answers). ``` ``` 10. (10) You have been transported through a wormhole to an alternate universe where everybody is using a language called *Mongoose*. But before you trust it, you need to make sure that it's **statically scoped** instead of dynamically scoped. *You had to jump into that wormhole because your planet was destroyed by aliens from Area 51. If this universe is not safe either you'll have to jump again!* Mongoose has the following syntax ``` let f = (lambda x. let y = x+1: x+y): cout (f 1) ``` This program prints 3. Write a Mongoose program that will show if the language is statically or dynamically scoped. Clearly indicate how to interpret the result of your experiment. ``` ``` 11. (10) Happy Holidays.