% Class 8: Git Yer Pointers Here
% David Evans
% 2013-09-12

<!--
Title: Class 8: Git Yer Pointers Here
Date: 2013-09-24
Category: Classes
Tags: Rust, smart pointers, garbage collection, memory management, Servo, LCLint
Author: David Evans
-->

<!-- <center>
<iframe src="http://www.slideshare.net/slideshow/embed_code/26363780" width="476" height="400" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>

</center>
-->

## Action Items

<div class="startaction"></div>

**<a href="http://www.cs.virginia.edu/evans/cs4414-fall2013/pages/ps2.html">PS2
is due Monday, September 30</a>.**  You should be at least up to Problem
4 by now.

**Before Thursday's class**, read either the paper or slides for
[_MapReduce: Simplified Data Processing on Large Clusters_](http://research.google.com/archive/mapreduce.html)
(Jeffrey Dean and Sanjay Ghemawat, Symposium on Operating System Design
and Implementation, December, 2004).  

<div class="endaction"></div>

# Lists in Rust

For this exercise, we'll implement a linked list data structure using
Rust.  (Note that the Rust library provides a [vector
type](http://static.rust-lang.org/doc/0.7/std/vec.html), so it is
unlikely you would want to use this linked list code, but it is a
worthwhile exercise to explore some issues in programming in Rust.)

## Version 1: Automatically Managed

````rust
struct Node { head : int, tail : Option<@Node> }
type List = Option<@Node> ;

impl ToStr for List {
    fn to_str(&self) -> ~str { 
        fn elements_to_str(n: @Node) -> ~str {
            match (n.tail) {
                None => fmt!("%?", n.head),
                Some(tail) => fmt!("%?, %s", n.head, elements_to_str(tail))
            }
        }
        
        match(*self) {
            None => ~"Null",
            Some(n) => fmt!("[%s]", elements_to_str(n))
} } } // don't do this unless you are printing 60 copies of your code

fn main() {
    let lst : List = 
        Some(@Node{head: 1, tail: 
          Some(@Node{head : 2, tail: 
            Some(@Node{head: 3, tail: None})})});
    println(fmt!("%s", lst.to_str()));
}
````

\newpage

## Version 2: Mutable List with Mapping

````rust
struct Node {
    head : int,
    tail : Option<@mut Node>
}

type List = Option<@mut Node> ;

trait Map {
    fn mapr(&self, &fn(int) -> int);
}

impl Map for List {
    // Thanks to dbaupp for figuring out why this breaks when called "map"!	
    fn mapr(&self, f: &fn(int) -> int) { 
        let mut current = *self;
        loop {
            match(current) {
                None => break,
                Some(node) => { node.head = f(node.head); current = node.tail },
            }
        }
    }
}

// ToStr removed to save space

fn main() {
    let lst : List = 
       Some(@mut Node{head: 1, tail: 
          Some(@mut Node{head : 2, tail: 
             Some(@mut Node{head: 3, tail: None})})});
    lst.mapr(|x: int| { x + 1 });
    lst.mapr(|x: int| { x * x });
    lst.mapr(|x: int| { if x % 2 == 0 { x } else { -x }});
    println(lst.to_str());
}
````


**Exercise 1.** Add an `append(&self, List)` method that appends two lists.  (You should think carefully about what semantics `append` should have
  before implementing it.)

**Exercise 2.** Add an `filtr(&self, &fn(int) -> bool)` method that removes elements for which a predicate is not true from a list.


 
