Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rust en contraste

Rust en contraste

Rust es un lenguaje a la vez de bajo nivel (pegado al metal) y alto nivel (con un gran poder de abstracción). ¿Cómo se logra esto? Lo exploraremos en contraste con lenguajes más habituales y otras tendencias actuales, echando un ojo a cómo queda en la práctica.

Toni Cárdenas

February 07, 2015
Tweet

Other Decks in Programming

Transcript

  1. Rust is a systems programming language that runs 
 blazingly

    fast, prevents almost all crashes, and
 eliminates data races.
  2. Contrastes • C: Tipos débiles, control crudo, sin runtime. •

    Python: Tipos dinámicos, control indirecto, runtime con GC. • Go: Tipos fuertes, control directo, runtime con concurrencia y GC. • C++: Tipos fuertes, control crudo, sin runtime. • Haskell: Tipos muy fuertes, memoria abstraída, runtime con concurrencia y GC.
  3. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p);
 return 0;
 }
  4. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p);
 return 0;
 } Point{x: 1, y:2} point{x: 1, y:2}
  5. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p);
 return 0;
 } Point{x: 1, y:2} point{x: 1, y:2}
  6. Point{x: 1, y:2} point{x: 1, y:2} point{x: 1, y:2} fn

    print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } void print_point(point p) {
 printf("(%d, %d)\n", p.x, p.y);
 } move
  7. fn print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } void

    print_point(point p) {
 printf("(%d, %d)\n", p.x, p.y);
 } Point{x: 1, y:2} point{x: 1, y:2} point{x: 1, y:2}
  8. fn print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } void

    print_point(point p) {
 printf("(%d, %d)\n", p.x, p.y);
 } point{x: 1, y:2}
  9. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p);
 return 0;
 } point{x: 1, y:2}
  10. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p);
 return 0;
 }
  11. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } p = Point(1, 2)
 print_point(p)

  12. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } Point{x: 1, y:2} p = p = Point(1, 2)
 print_point(p)
 point{x: 1, y:2}
  13. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } Point{x: 1, y:2} p = p = Point(1, 2)
 print_point(p)
 point{x: 1, y:2}
  14. Point{x: 1, y:2} fn print_point(p: Point) {
 println!("({}, {})", p.x,

    p.y);
 } p = def print_point(p):
 print('(%s, %s)' % (p.x, p.y))
 point{x: 1, y:2} p =
  15. fn print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } Point{x:

    1, y:2} p = def print_point(p):
 print('(%s, %s)' % (p.x, p.y))
 point{x: 1, y:2} p =
  16. fn print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } p

    = def print_point(p):
 print('(%s, %s)' % (p.x, p.y))
 point{x: 1, y:2}
  17. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } p = Point(1, 2)
 print_point(p)
 point{x: 1, y:2}
  18. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p);
 } p = Point(1, 2)
 print_point(p)
 point{x: 1, y:2}
  19. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p); print_point(p);
 return 0;
 }
  20. Point{x: 1, y:2} point{x: 1, y:2} fn main() {
 let

    p = Point{x: 1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p); print_point(p);
 return 0;
 }
  21. Point{x: 1, y:2} point{x: 1, y:2} fn main() {
 let

    p = Point{x: 1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p); print_point(p);
 return 0;
 }
  22. Point{x: 1, y:2} point{x: 1, y:2} point{x: 1, y:2} fn

    print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } void print_point(point p) {
 printf("(%d, %d)\n", p.x, p.y);
 }
  23. fn print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } void

    print_point(point p) {
 printf("(%d, %d)\n", p.x, p.y);
 } Point{x: 1, y:2} point{x: 1, y:2} point{x: 1, y:2}
  24. fn print_point(p: Point) {
 println!("({}, {})", p.x, p.y);
 } void

    print_point(point p) {
 printf("(%d, %d)\n", p.x, p.y);
 } point{x: 1, y:2}
  25. point{x: 1, y:2} fn main() {
 let p = Point{x:

    1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(p); print_point(p);
 return 0;
 } ERROR!!! error: use of moved value: `p`
  26. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(&p); print_point(&p);
 return 0;
 }
  27. Point{x: 1, y:2} point{x: 1, y:2} fn main() {
 let

    p = Point{x: 1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(&p); print_point(&p);
 return 0;
 }
  28. Point{x: 1, y:2} point{x: 1, y:2} fn main() {
 let

    p = Point{x: 1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(&p); print_point(&p);
 return 0;
 }
  29. point{x: 1, y:2} p = & fn print_point(p: &Point) {


    println!("({}, {})", p.x, p.y);
 } void print_point(point* p) {
 printf("(%d, %d)\n", p->x, p->y);
 } p = & Point{x: 1, y:2} borrow
  30. fn print_point(p: &Point) {
 println!("({}, {})", p.x, p.y);
 } void

    print_point(point* p) {
 printf("(%d, %d)\n", p->x, p->y);
 } point{x: 1, y:2} p = & p = & Point{x: 1, y:2}
  31. fn print_point(p: &Point) {
 println!("({}, {})", p.x, p.y);
 } void

    print_point(point* p) {
 printf("(%d, %d)\n", p->x, p->y);
 } point{x: 1, y:2} Point{x: 1, y:2}
  32. point{x: 1, y:2} fn main() {
 let p = Point{x:

    1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(&p); print_point(&p);
 return 0;
 } Point{x: 1, y:2}
  33. point{x: 1, y:2} fn main() {
 let p = Point{x:

    1, y: 2};
 print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(&p); print_point(&p);
 return 0;
 }
  34. fn main() {
 let p = Point{x: 1, y: 2};


    print_point(p); print_point(p);
 } int main() {
 point p = {.x = 1, .y = 2};
 print_point(&p); print_point(&p);
 return 0;
 }
  35. p = make_point() 
 print_point(p) fn main() {
 let p

    = make_point();
 print_point(p); }
  36. p = make_point() 
 print_point(p) fn main() {
 let p

    = make_point();
 print_point(p); }
  37. def make_point():
 return Point(1, 2) fn make_point() -> Point {


    Point{x: 1, y: 2}
 } point{x: 1, y:2} Point{x: 1, y:2}
  38. Point{x: 1, y:2} p = point{x: 1, y:2} p =

    make_point() 
 print_point(p) fn main() {
 let p = make_point();
 print_point(p); }
  39. Point{x: 1, y:2} p = point{x: 1, y:2} p =

    make_point() 
 print_point(p) fn main() {
 let p = make_point();
 print_point(p); }
  40. p = make_point() 
 print_point(p) fn main() {
 let p

    = make_point();
 print_point(p); } point{x: 1, y:2}
  41. p = make_point() 
 print_point(p) fn main() {
 let p

    = make_point();
 print_point(p); } point{x: 1, y:2}
  42. p = make_point() 
 print_point(p) fn main() {
 let p

    = make_point();
 print_point(p); }
  43. p = make_point() 
 print_point(p) fn main() {
 let p

    = make_point();
 print_point(p); }
  44. def make_point():
 return Point(1, 2) point{x: 1, y:2} Point{x: 1,

    y:2} fn make_point() -> &Point {
 &Point{x: 1, y: 2}
 }
  45. p = & p = point{x: 1, y:2} p =

    make_point() 
 print_point(p) fn main() {
 let p = make_point();
 print_point(p); } ERROR!!! error: missing lifetime specifier
  46. p = & p = & int main() {
 point*

    p = make_point();
 print_point(p);
 return 0;
 } fn main() {
 let p = make_point();
 print_point(p); } ERROR!!! error: missing lifetime specifier
  47. p = & p = & int main() {
 point*

    p = make_point();
 print_point(p);
 return 0;
 } fn main() {
 let p = make_point();
 print_point(p); } ERROR!!! error: missing lifetime specifier (1571071448, 32767)
  48. p = & p = & int main() {
 point*

    p = make_point();
 print_point(p);
 return 0;
 } fn main() {
 let p = make_point();
 print_point(p); } ERROR!!! error: missing lifetime specifier
  49. p = & int main() {
 point* p = make_point();


    print_point(p);
 return 0;
 } fn main() {
 let p = make_point();
 print_point(p); } ERROR!!! error: missing lifetime specifier
  50. p = make_point() 
 print_point(p) fn main() {
 let p

    = &*make_point();
 print_point(p); }
  51. p = make_point() 
 print_point(p) fn main() {
 let p

    = &*make_point();
 print_point(p); }
  52. def make_point():
 return Point(1, 2) point{x: 1, y:2} p =

    box fn make_point() -> Box<Point> {
 Box::new(Point{x: 1, y: 2})
 } Point{x: 1, y:2}
  53. p = & p = point{x: 1, y:2} p =

    make_point() 
 print_point(p) fn main() {
 let p = &*make_point();
 print_point(p); } Point{x: 1, y:2}
  54. p = & p = point{x: 1, y:2} p =

    make_point() 
 print_point(p) fn main() {
 let p = &*make_point();
 print_point(p); } Point{x: 1, y:2}
  55. point{x: 1, y:2} p = make_point() 
 print_point(p) fn main()

    {
 let p = &*make_point();
 print_point(p); } Point{x: 1, y:2}
  56. p = make_point() 
 print_point(p) fn main() {
 let p

    = &*make_point();
 print_point(p); } point{x: 1, y:2}
  57. p = & int main() {
 point* p = make_point();


    print_point(p);
 return 0;
 } p = & fn main() {
 let p = &*make_point();
 print_point(p); } Point{x: 1, y:2} point{x: 1, y:2}
  58. int main() {
 point* p = make_point();
 print_point(p);
 return 0;


    } (1, 2) p = & fn main() {
 let p = &*make_point();
 print_point(p); } Point{x: 1, y:2} p = & point{x: 1, y:2} (1, 2)
  59. int main() {
 point* p = make_point();
 print_point(p);
 return 0;


    } fn main() {
 let p = &*make_point();
 print_point(p); } point{x: 1, y:2} Point{x: 1, y:2}
  60. int main() {
 point* p = make_point();
 print_point(p);
 return 0;


    } fn main() {
 let p = &*make_point();
 print_point(p); } point{x: 1, y:2}
  61. int main() {
 point* p = make_point();
 print_point(p);
 return 0;


    } fn main() {
 let p = &*make_point();
 print_point(p); } point{x: 1, y:2} 10 horas más tarde...
  62. Ownership Los valores pertenecen a un scope. Los valores se

    prestan durante un scope. Borrow inmutable Borrow mutable Move Point{x: 1, y:2} Point{x: 1, y:2} • Copia de memoria. • Original no reutilizable. Point{x: 1, y:2} & Point{x: 1, y:2} • Puntero. • Original inutilizado. • Puede haber varios en
 un mismo scope. Point{x: 1, y:2} & Point{x: 1, y:2} • Puntero. • Original inutilizado. • Sólo uno en un mismo
 scope.
  63. – Alfred N. Whitehead “Civilization advances by extending the number

    of important operations which we can perform without thinking about them.”
  64. – Rob Pike: Less is exponentially more “Bell Labs centers

    were originally assigned three-letter numbers: 111 for Physics Research, 127 for Computing Sciences Research, and so on. In the early 1980s a memo came around announcing that as our understanding of research had grown, it had become necessary to add another digit so we could better characterize our work. So our center became 1127. Ron Hardin joked, half-seriously, that if we really understood our world better, we could drop a digit and go down from 127 to just 27.”
  65. Tipos: ¿qué son? • ¿Anotaciones de cuánta memoria ocupa cada

    variable y cada valor? • ¿Taxonomía del dominio de nuestro programa, con operaciones asociadas? • ¿Lo que el compilador puede comprobar por nosotros sobre nuestros valores, variables y operaciones?
  66. Tipado estático • Potente abstracción. • Que el compilador puede

    comprobar. • Y que, adicionalmente, puede ayudar al compilador a compilar eficientemente. • En Rust, con este significado, incluye las reglas de ownership (borrow checker).
  67. let m: Option<MyType> = None; if let Some(x) = m

    { x.do_something(); }
 m.and_then(|&x| { x.do_something(); }
 match m { case Some(x) => { x.do_something(); }, case None => { ... }, }
  68. El coste de la abstracción Lo que en C parece...

    ... en realidad es... time_t* t = add_duration(&times[i], duration); free(t); No hay abstracción = No hay coste time_t* t = add_duration(&times[i], duration); free(t);
  69. El coste de la abstracción Lo que en Go parece...

    ... en realidad es... t := times[i].Add(duration) if (times.len < i) {
 panic(__static_bounds_err);
 }
 *Time t = Time_Add(times->contents[i], duration); garbage_collector();
 scheduler();
 Coste de la runtime = ¿?
  70. El coste de la abstracción Lo que en Python parece...

    ... en realidad es... t = times[i].add(duration) Obj* times = lookup(scope, 'times');
 Obj* gi = lookup(times->attrs, '__getitem__');
 Obj* call = lookup(gi, '__call__');
 Obj* i = lookup(scope, 'i');
 Obj* args = make_args(2); // Malloc, etc.
 Obj* kwargs = make_kwargs(0);
 args[0] = times;
 args[1] = i;
 // Incluye bounds checking, lookups, etc.
 Obj* t = call->call(args, kwargs);
 Obj* add = lookup(t->attrs, 'add');
 call = lookup(add, '__call__');
 Obj* duration = lookup(scope, 'duration');
 args = make_args(2); // Malloc, etc.

  71. args = make_args(2); // Malloc, etc.
 Obj* kwargs = make_kwargs(0);


    args[0] = t;
 args[1] = duration;
 t = call->call(args, kwargs); Más: coste de la runtime (GC)
  72. El coste de la abstracción Lo que en Rust parece...

    ... en realidad es... let t = times[i].add(duration); if (times.len < i) {
 panic(__static_bounds_err);
 }
 *Time t = Time_add(times->contents[i], duration); drop(t); Coste de la runtime = ninguno
  73. El coste de la abstracción Lo que en Go parece...

    ... en realidad es... t := times.At(i).(*Time).Add(duration) if (LinkedList_Length(&times) < i) {
 panic(__static_bounds_err);
 }
 Iface* at = LinkedList_At(&times, i);
 if (at->type != __type__time_ptr) {
 panic(__static_type_assert);
 }
 if (at->value == NULL) {
 panic(__static_null_ptr);
 }
 Time* t = Time_Add((Time*)at->value,
 duration);
 garbage_collector();
 scheduler(); Dynamic dispatch
  74. El coste de la abstracción Lo que en Rust parece...

    ... en realidad es... let t = times[i].add(duration); if (LinkedList_Length_for_Time_ptr( &times) < i) {
 panic(__static_bounds_err);
 }
 Time* at = LinkedList_At_for_Time_ptr( &times, i);
 Time* t = Time_Add(at, duration);
 drop(t); Tipos genéricos = Static dispatch
  75. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 }
  76. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 } Point{x: 1, y:2}
  77. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 } Point{x: 1, y:2}
  78. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 } Point{x: 1, y:2} p = & || {
 timer::sleep(Duration::seconds(1));
 print_point(&p);
 }
  79. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 } Point{x: 1, y:2} p = & || {
 timer::sleep(Duration::seconds(1));
 print_point(&p);
 }
  80. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 } p = & || {
 timer::sleep(Duration::seconds(1));
 print_point(&p);
 }
  81. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 println!("Created {} and ...
 } p = & || {
 timer::sleep(Duration::seconds(1));
 print_point(&p);
 } ERROR!!! error: cannot infer an appropriate lifetime due to conflicting requirements
  82. fn make_point_and_print_later() {
 let p = Point{x: 1, y: 2};


    Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&p);
 });
 } Point{x: 1, y:2} || {
 timer::sleep(Duration::seconds(1));
 print_point(&p);
 }
  83. Go

  84. func makePointAndPrintLater() {
 p := Point{x: 1, y: 2}
 go

    func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 }
  85. Point{x: 1, y:2} func makePointAndPrintLater() {
 p := Point{x: 1,

    y: 2}
 go func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 }
  86. Point{x: 1, y:2} func makePointAndPrintLater() {
 p := Point{x: 1,

    y: 2}
 go func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } p = & func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }
  87. p = & func makePointAndPrintLater() {
 p := Point{x: 1,

    y: 2}
 go func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } p = & func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  88. p = & func makePointAndPrintLater() {
 p := Point{x: 1,

    y: 2}
 go func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } p = & func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  89. p = & func makePointAndPrintLater() {
 p := Point{x: 1,

    y: 2}
 go func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } p = & func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  90. func makePointAndPrintLater() {
 p := Point{x: 1, y: 2}
 go

    func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } p = & func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  91. func makePointAndPrintLater() {
 p := Point{x: 1, y: 2}
 go

    func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } p = & func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  92. func makePointAndPrintLater() {
 p := Point{x: 1, y: 2}
 go

    func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  93. func makePointAndPrintLater() {
 p := Point{x: 1, y: 2}
 go

    func() {
 time.Sleep(time.Second)
 printPoint(&p)
 }()
 fmt.Printf("Created %v and...
 } func() {
 time.Sleep(time.Second)
 printPoint(&p)
 } point{x: 1, y:2}
  94. fn make_point_and_print_later() {
 let p = Arc::new( Point{x: 1, y:

    2});
 let p_ref = p.clone();
 Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&*p_ref);
 });
 println!("Created {} and ...
 } point{x: 1, y:2} refs = 2 p = arc p_ref = arc
  95. fn make_point_and_print_later() {
 let p = Arc::new( Point{x: 1, y:

    2});
 let p_ref = p.clone();
 Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&*p_ref);
 });
 println!("Created {} and ...
 } p_ref = arc || {
 timer::sleep(Duration::seconds(1));
 print_point(&*p_ref);
 } point{x: 1, y:2} refs = 2 p = arc
  96. fn make_point_and_print_later() {
 let p = Arc::new( Point{x: 1, y:

    2});
 let p_ref = p.clone();
 Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&*p_ref);
 });
 println!("Created {} and ...
 } p_ref = arc || {
 timer::sleep(Duration::seconds(1));
 print_point(&*p_ref);
 } point{x: 1, y:2} refs = 2 p = arc
  97. fn make_point_and_print_later() {
 let p = Arc::new( Point{x: 1, y:

    2});
 let p_ref = p.clone();
 Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&*p_ref);
 });
 println!("Created {} and ...
 } p_ref = arc || {
 timer::sleep(Duration::seconds(1));
 print_point(&*p_ref);
 } point{x: 1, y:2} refs = 1
  98. fn make_point_and_print_later() {
 let p = Arc::new( Point{x: 1, y:

    2});
 let p_ref = p.clone();
 Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&*p_ref);
 });
 println!("Created {} and ...
 } p_ref = arc || {
 timer::sleep(Duration::seconds(1));
 print_point(&*p_ref);
 } point{x: 1, y:2} refs = 1
  99. fn make_point_and_print_later() {
 let p = Arc::new( Point{x: 1, y:

    2});
 let p_ref = p.clone();
 Thread::spawn(move|| {
 timer::sleep( Duration::seconds(1));
 print_point(&*p_ref);
 });
 println!("Created {} and ...
 } || {
 timer::sleep(Duration::seconds(1));
 print_point(&*p_ref);
 } point{x: 1, y:2} refs = 0
  100. • Rust no te da: • Runtime (Garbage Collector, green

    threads) • Integración de features en el lenguaje • Rust te da: • Ownership. • Sistema de tipos moderno y potente.