###
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.