final state of first presentation
Getty Ritter
9 years ago
1 | 1 | % The Rust Programming Language |
2 | 2 | % G.D. Ritter |
3 |
% |
|
3 | % June 2015 | |
4 | 4 | |
5 | 5 | # The Rust Programming Language |
6 | 6 | |
41 | 41 | |
42 | 42 | ## Example Program |
43 | 43 | |
44 | ~~~~{.haskell} | |
45 | data Point = { x, y : Int } | |
46 | ||
47 | addPoint : Point -> Point -> Point | |
48 | addPoint l r = { x = l.x + r.x, y = l.y + r.y } | |
49 | ||
50 | main : () | |
51 | main = { let a = { x = 1, y = 2 } | |
52 | ; let b = malloc { x = 4, y = 3} | |
53 | ; print (addPoint a (deref b)) | |
54 | ; free(b) | |
55 | } | |
56 | ~~~~ | |
44 | A program that: | |
45 | ||
46 | - Defines a `point` struct. | |
47 | - Gives that `point` struct two machine integers as | |
48 | fields. | |
49 | - Defines an `add` function that takes and returns | |
50 | two `point`s _by value_. | |
51 | - Has a `main` function that: | |
52 | - Creates a `point` on the stack | |
53 | - Creates a `point` on the heap | |
54 | - Adds the two (after dereferencing the second) | |
55 | - Prints the result | |
56 | - Frees the second point | |
57 | 57 | |
58 | 58 | # Systems Programming Languages |
59 | 59 | |
166 | 166 | ## Rust |
167 | 167 | |
168 | 168 | ~~~~{.rust} |
169 | #[derive(Debug,Clone,Copy)] | |
169 | 170 | struct Point { x: isize, y: isize } |
170 | 171 | |
171 | impl Point { | |
172 | fn add(self, other: Point) -> Point { | |
173 | Point { x: self.x + other.x, | |
174 | y: self.y + other.y } | |
175 | } | |
172 | fn add(l: Point, r: Point) -> Point { | |
173 | Point { x: l.x + r.x, y: l.y + r.y } | |
176 | 174 | } |
177 | 175 | |
178 | 176 | fn main() { |
179 | 177 | let a = Point { x: 1, y: 2 }; |
180 | 178 | let b = Box::new(Point { x: 4, y: 3 }); |
181 | println!("{:?}", a.add(*b)); | |
182 | } | |
183 | ~~~~ | |
184 | ||
185 | # What Makes Rust Interesting | |
186 | ||
187 | > It's like C++ grew up, went to grad school, started dating Haskell, and | |
188 | > is sharing an office with Erlang... | |
189 | > | |
190 | > —Michael Sullivan | |
179 | println!("{:?}", add(a, *b)); | |
180 | } | |
181 | ~~~~ | |
191 | 182 | |
192 | 183 | # What Makes Rust Interesting |
193 | 184 | |
197 | 188 | \includegraphics[width=.9\textwidth]{imgs/dawkins-owned.png} |
198 | 189 | \end{center} |
199 | 190 | |
200 | ## Ownership | |
201 | ||
202 | ~~~~{.rust} | |
203 | #[derive(Debug)] | |
204 | struct MyNum { num: i32 } | |
205 | ||
206 | fn main() { | |
207 | let x = MyNum { num: 2 }; | |
208 | println!("x = {:?}", x); | |
209 | } | |
210 | ~~~~ | |
211 | ||
212 |
# |
|
191 | # Preliminary Zero | |
192 | ## Mutability | |
193 | ||
194 | ~~~~{.rust} | |
195 | fn factorial(n: usize) -> usize { | |
196 | let result = 1; | |
197 | while n > 0 { | |
198 | result *= n; | |
199 | n -= 1; | |
200 | } | |
201 | result | |
202 | } | |
203 | ~~~~ | |
204 | ||
205 | # Preliminary Zero | |
206 | ## Mutability is NOT THE DEFAULT | |
207 | ||
208 | ~~~~{.rust} | |
209 | fn factorial(n: usize) -> usize { | |
210 | let result = 1; | |
211 | while n > 0 { | |
212 | result *= n; /* ERROR */ | |
213 | n -= 1; /* ERROR */ | |
214 | } | |
215 | result | |
216 | } | |
217 | ~~~~ | |
218 | ||
219 | # Preliminary Zero | |
220 | ## Mutability is Opt-In | |
221 | ||
222 | ~~~~{.rust} | |
223 | fn factorial(mut n: usize) -> usize { | |
224 | let mut result = 1; | |
225 | while n > 0 { | |
226 | result *= n; | |
227 | n -= 1; | |
228 | } | |
229 | result | |
230 | } | |
231 | ~~~~ | |
232 | ||
233 | # Preliminary One | |
234 | ## Polymorphism (although not on this slide) | |
235 | ||
236 | ~~~~{.rust} | |
237 | fn i32_id(a: i32) -> i32 { | |
238 | a | |
239 | } | |
240 | ||
241 | fn make_i32_pair(left: i32, right: i32) -> (i32, i32) { | |
242 | (left, right) | |
243 | } | |
244 | ~~~~ | |
245 | ||
246 | # Preliminary One | |
247 | ## Polymorphism (this slide is, like, _totally_ polymorphic) | |
248 | ||
249 | ~~~~{.rust} | |
250 | fn id<T>(a: T) -> T { | |
251 | a | |
252 | } | |
253 | ||
254 | fn make_pair<A, B>(left: A, right: B) -> (A, B) { | |
255 | (left, right) | |
256 | } | |
257 | ~~~~ | |
258 | ||
259 | # Preliminary Two | |
213 | 260 | ## Traits |
214 | 261 | |
215 | 262 | ~~~~{.rust} |
216 | trait ToString { | |
217 | fn to_string(&self) -> String; | |
218 | } | |
219 | ||
220 | impl ToString for () { | |
221 | fn to_string(&self) -> String { | |
222 | "unit".to_owned() | |
223 | } | |
224 | } | |
225 | ~~~~ | |
226 | ||
227 | # Brief Aside | |
263 | struct MyNum { num: i32 } | |
264 | ||
265 | trait Sayable { | |
266 | fn say(&self); | |
267 | } | |
268 | ||
269 | impl Sayable for MyNum { | |
270 | fn say(&self) { | |
271 | println!(".oO( MyNum {{ num: {:?} }} )", self.num); | |
272 | } | |
273 | } | |
274 | ~~~~ | |
275 | ||
276 | # Preliminary Two | |
228 | 277 | ## Traits |
229 | 278 | |
230 | 279 | ~~~~{.rust} |
231 | fn print_excitedly<T: ToString>(t: T) { | |
232 | println!("{}!!!", t.to_string()); | |
233 | } | |
234 | ||
235 | fn main() { | |
236 | print_excitedly( () ); | |
237 | } | |
238 | ~~~~ | |
239 | ||
240 | # Brief Aside from the Brief Aside | |
241 | ## Polymorphism | |
242 | ||
243 | ~~~~{.rust} | |
244 | fn make_pair<A, B>(a: A, b: B) -> (A, B) { | |
245 | (a, b) | |
246 | } | |
247 | ||
248 | fn not_eq<A: Eq>(left: A, right: A) -> bool { | |
249 | left != right | |
250 | } | |
251 | ~~~~ | |
252 | ||
253 | # Brief Aside from the Brief Aside | |
254 | ## Polymorphism | |
255 | ||
256 | ~~~~{.rust} | |
257 |
fn |
|
280 | fn main() { | |
281 | (MyNum { num: 3 }).say(); | |
282 | } | |
283 | ~~~~ | |
284 | ||
285 | ## Output | |
286 | ~~~~ | |
287 | .oO( MyNum { num: 3 } ) | |
288 | ~~~~ | |
289 | ||
290 | # Preliminary Three | |
291 | ## Traits _and_ Polymorphism | |
292 | ||
293 | ~~~~{.rust} | |
294 | fn say_twice<T: Sayable>(t: T) { | |
295 | t.say(); t.say(); | |
296 | } | |
297 | ||
298 | fn main() { | |
299 | say_twice(MyNum { num: 7 }); | |
300 | } | |
301 | ~~~~ | |
302 | ||
303 | ## Output | |
304 | ~~~~ | |
305 | .oO( NyNum { num: 7 } ) | |
306 | .oO( NyNum { num: 7 } ) | |
307 | ~~~~ | |
308 | ||
309 | # Preliminary Three | |
310 | ## Traits _and_ Polymorphism | |
311 | ||
312 | ~~~~{.rust} | |
313 | fn print_eq<A: Eq + Sayable>(left: A, right: A) { | |
258 | 314 | if left == right { |
259 | println!("{} and {} are equal", | |
260 | left.to_string(), | |
261 |
|
|
315 | println!("these are equal:"); | |
316 | left.say(); | |
317 | right.say(); | |
262 | 318 | } else { |
263 | println!("{} and {} are different", | |
264 | left.to_string(), | |
265 | right.to_string()); | |
266 | } | |
267 | } | |
268 | ~~~~ | |
269 | ||
270 | # Brief Aside | |
271 | ## Traits | |
272 | ||
273 | ~~~~{.rust} | |
274 | /* this is /slightly/ different in the stdlib */ | |
275 | trait PartialEq<Rhs> { | |
276 | fn eq(&self, other: &Rhs) -> bool; | |
277 |
|
|
319 | println!("these are not equal:"); | |
320 | left.say(); | |
321 | right.say(); | |
322 | } | |
323 | } | |
324 | ~~~~ | |
325 | ||
326 | # Preliminary Four | |
327 | ## Built-In Traits | |
328 | ||
329 | ~~~~{.rust} | |
330 | /* slightly simplified from the real definition */ | |
331 | trait PartialEq { | |
332 | fn eq(&self, other: &Self) -> bool; | |
333 | fn ne(&self, other: &Self) -> bool; | |
278 | 334 | } |
279 | 335 | |
280 | 336 | /* no more methods, but more laws */ |
281 | trait Eq: PartialEq<Self> { } | |
282 | ~~~~ | |
283 | ||
284 | # Brief Aside | |
285 | ## Traits | |
286 | ||
287 | ~~~~{.rust} | |
288 | struct MyNum { num: i32 } | |
289 | ||
290 | impl PartialEq<MyNum> for MyNum { | |
337 | trait Eq: PartialEq { } | |
338 | ~~~~ | |
339 | ||
340 | # Preliminary Four | |
341 | ## Implementing Built-In Traits | |
342 | ||
343 | ~~~~{.rust} | |
344 | struct MyNum { num: i32 } | |
345 | ||
346 | impl PartialEq for MyNum { | |
291 | 347 | fn eq(&self, other: &MyNum) -> bool { |
292 | 348 | self.num == other.num |
293 | 349 | } |
296 | 352 | impl Eq for MyNum { } |
297 | 353 | ~~~~ |
298 | 354 | |
299 | # Brief Aside | |
300 | ## Traits | |
355 | # Preliminary Four | |
356 | ## Implementing Built-In Traits Automatically | |
301 | 357 | |
302 | 358 | ~~~~{.rust} |
303 | 359 | /* or just this */ |
305 | 361 | struct MyNum { num: i32 } |
306 | 362 | ~~~~ |
307 | 363 | |
308 | # What Makes Rust Interesting | |
309 | ||
364 | # Preliminary Four | |
365 | ## Format-String-Related Traits | |
366 | ||
367 | ~~~~{.rust} | |
368 | /* in the stdlib: */ | |
369 | trait Debug { | |
370 | fn fmt(&self, &mut Formatter) -> Result; | |
371 | } | |
372 | ||
373 | /* so, on on our type: */ | |
374 | #[derive(Debug)] | |
375 | struct MyNum { num: i32 } | |
376 | ~~~~ | |
377 | ||
378 | # What Makes Rust Interesting | |
310 | 379 | ## Ownership |
311 | 380 | |
312 | 381 | ~~~~{.rust} |
315 | 384 | |
316 | 385 | fn main() { |
317 | 386 | let x = MyNum { num: 2 }; |
387 | ||
388 | println!("x = {:?}", x); | |
389 | /* prints "x = MyNum { num: 2 }" */ | |
390 | } | |
391 | ~~~~ | |
392 | ||
393 | # What Makes Rust Interesting | |
394 | ||
395 | ## Ownership | |
396 | ||
397 | ~~~~{.rust} | |
398 | #[derive(Debug)] | |
399 | struct MyNum { num: i32 } | |
400 | ||
401 | fn main() { | |
402 | let x = MyNum { num: 2 }; | |
318 | 403 | let y = x; |
319 | 404 | println!("x = {:?}", x); |
320 | ||
405 | /* doesn't compile */ | |
321 | 406 | } |
322 | 407 | ~~~~ |
323 | 408 | |
349 | 434 | let x = MyNum { num: 2 }; |
350 | 435 | let y = x; |
351 | 436 | println!("x = {:?}", x); |
352 |
/* so |
|
437 | /* so it does not live until the print */ | |
353 | 438 | } |
354 | 439 | ~~~~ |
355 | 440 | |
363 | 448 | |
364 | 449 | fn main() { |
365 | 450 | let x = MyNum { num: 2 }; |
366 | let y = x.clone(); | |
367 | println!("x = {:?}", x); | |
368 |
|
|
451 | let y = x.clone(); /* explicit clone */ | |
452 | println!("x = {:?}", x); | |
453 | /* but this works! */ | |
369 | 454 | } |
370 | 455 | ~~~~ |
371 | 456 | |
379 | 464 | |
380 | 465 | fn main() { |
381 | 466 | let x = MyNum { num: 2 }; |
382 |
let y = x; |
|
467 | let y = x; /* implicit copy */ | |
383 | 468 | println!("x = {:?}", x); |
384 | 469 | /* as does this! */ |
385 | 470 | } |
403 | 488 | let x = MyNum { num: 2 }; |
404 | 489 | println!("x = {:?}", x); |
405 | 490 | } |
491 | ~~~~ | |
492 | ||
493 | # What Makes Rust Interesting | |
494 | ||
495 | ## Ownership --- Destructors | |
496 | ||
497 | ~~~~{.rust} | |
498 | fn main() { | |
499 | let x = MyNum { num: 2 }; | |
500 | println!("x = {:?}", x); | |
501 | } | |
502 | ~~~~ | |
503 | ||
504 | ## Output | |
505 | ||
506 | ~~~~ | |
507 | x = MyNum { num: 2 } | |
508 | dropping: MyNum { num: 2 } | |
406 | 509 | ~~~~ |
407 | 510 | |
408 | 511 | # What Makes Rust Interesting |
423 | 526 | fn main() { |
424 | 527 | let x = MyNum { num: 2 }; |
425 | 528 | let y = x.clone(); |
426 |
println!("x = {:?}", |
|
529 | println!("x = {:?}", x); | |
530 | } | |
531 | ~~~~ | |
532 | ||
533 | ## Ownership --- Special Clones | |
534 | ||
535 | ~~~~{.rust} | |
536 | fn main() { | |
537 | let x = MyNum { num: 2 }; | |
538 | let y = x.clone() | |
539 | println!("x = {:?}", x); | |
540 | } | |
541 | ~~~~ | |
542 | ||
543 | ## Output | |
544 | ||
545 | ~~~~ | |
546 | Cloning a MyNum... | |
547 | x = MyNum { num: 2 } | |
548 | ~~~~ | |
549 | ||
550 | # What Makes Rust Interesting | |
551 | ## Owned Pointers --- "Boxes" | |
552 | ||
553 | ~~~~{.rust} | |
554 | fn main() { | |
555 | ||
556 | let x = Box::new(5); | |
557 | ||
558 | println!("x + 1 = {:?}", *x + 1); | |
559 | ||
560 | ||
561 | } | |
562 | ~~~~ | |
563 | ||
564 | # What Makes Rust Interesting | |
565 | ## Owned Pointers --- "Boxes" | |
566 | ||
567 | ~~~~{.rust} | |
568 | fn main() { | |
569 | /* this acts like a `malloc` */ | |
570 | let x = Box::new(5); | |
571 | /* this dereferences the pointer */ | |
572 | println!("x + 1 = {:?}", *x + 1); | |
573 | /* as soon as ownership passes out | |
574 | * of scope, the box is freed */ | |
427 | 575 | } |
428 | 576 | ~~~~ |
429 | 577 | |
520 | 668 | ## References |
521 | 669 | |
522 | 670 | ~~~~{.rust} |
523 |
#[derive(Debug |
|
671 | #[derive(Debug)] | |
524 | 672 | struct MyNum { num: i32 } |
525 | 673 | |
526 | 674 | fn some_func(_: &MyNum) { |
534 | 682 | /* works! */ |
535 | 683 | } |
536 | 684 | ~~~~ |
685 | ||
686 | # What Makes Rust Interesting | |
687 | ||
688 | ## Dangling References...? | |
689 | ||
690 | ~~~~{.rust} | |
691 | fn main() { | |
692 | let mut my_ref: &i32 = &5; | |
693 | { | |
694 | let x = 7; | |
695 | my_ref = &x; | |
696 | } | |
697 | println!("{:?}", my_ref); | |
698 | } | |
699 | ~~~~ | |
700 | ||
701 | # What Makes Rust Interesting | |
702 | ||
703 | ## Dangling References... are statically prevented | |
704 | ||
705 | ~~~~{.rust} | |
706 | fn main() { | |
707 | let mut my_ref: &i32 = &5; | |
708 | { | |
709 | let x = 7; | |
710 | my_ref = &x; /* ERROR: does not live long enough */ | |
711 | } | |
712 | println!("{:?}", my_ref); | |
713 | } | |
714 | ~~~~ | |
715 | ||
716 | ||
717 | # What Makes Rust Interesting | |
718 | ||
719 | ## "The Borrow Checker" | |
720 | ||
721 | ~~~~{.rust} | |
722 | fn main() { | |
723 | let mut my_vec = vec![]; | |
724 | { | |
725 | let x = 7; | |
726 | my_vec.push(&x); /* also a problem */ | |
727 | } | |
728 | println!("{:?}", my_vec); | |
729 | } | |
730 | ~~~~ | |
731 | ||
732 | # What Makes Rust Interesting | |
733 | ||
734 | ## Lifetime Quandary | |
735 | ||
736 | ~~~~{.rust} | |
737 | fn keep_left<T>(left: &T, right: &T) -> &T { | |
738 | left | |
739 | } | |
740 | ~~~~ | |
741 | ||
742 | # What Makes Rust Interesting | |
743 | ||
744 | ## Lifetime Quandary | |
745 | ||
746 | ~~~~{.rust} | |
747 | fn keep_left<'l, 'r, T>(left: &l T, | |
748 | right: &r T) -> &l T { | |
749 | left | |
750 | } | |
751 | ~~~~ | |
752 | ||
753 | # A Slightly Longer Example | |
754 | ||
755 | ## A Linked List | |
756 | ||
757 | ~~~~{.rust} | |
758 | #[derive(Debug)] | |
759 | enum List<T> { | |
760 | Cons(T, Box<List<T>>), | |
761 | Nil, | |
762 | } | |
763 | ||
764 | fn cons<T>(car: T, cdr: List<T>) -> List<T> { | |
765 | List::Cons(car, Box::new(cdr)) | |
766 | } | |
767 | ||
768 | fn nil<T>() -> List<T> { | |
769 | List::Nil | |
770 | } | |
771 | ~~~~ | |
772 | ||
773 | # A Slightly Longer Example | |
774 | ||
775 | ## A Linked List | |
776 | ||
777 | ~~~~{.rust} | |
778 | fn head<T>(list: &List<T>) -> Option<&T> { | |
779 | match *list { | |
780 | Nil => None, | |
781 | Cons(ref x, _) => Some(&x), | |
782 | } | |
783 | } | |
784 | ~~~~ | |
785 | ||
786 | # A Slightly Longer Example | |
787 | ||
788 | ## A Linked List Lifetime | |
789 | ||
790 | ~~~~{.rust} | |
791 | fn main() { | |
792 | let mut h = None; | |
793 | { | |
794 | let lst = cons("this", | |
795 | cons("that", | |
796 | cons("the other", | |
797 | nil()))); | |
798 | h = head(lst); | |
799 | } | |
800 | println!("{:?}", h); | |
801 | } | |
802 | ~~~~ | |
803 | ||
804 | ||
805 | # A Slightly Longer Example | |
806 | ||
807 | ## Linked List: A Lifetime Original Picture | |
808 | ||
809 | ~~~~{.rust} | |
810 | fn head<'a, T>(list: &'a List<T>) -> Option<&'a T> { | |
811 | match *list { | |
812 | Nil => None, | |
813 | Cons(ref x, _) => Some(&x), | |
814 | } | |
815 | } | |
816 | ~~~~ | |
817 | ||
818 | # A Slightly Longer Example | |
819 | ||
820 | ## Linked List: A Lifetime Original Picture | |
821 | ||
822 | ~~~~{.rust} | |
823 | fn polycephaly<T>(left: &List<T>, right: &List<T>) | |
824 | -> Option<(&T, &T)> { | |
825 | match (*left, *right) { | |
826 | (List::Nil, List::Nil) => None, | |
827 | (List::Cons(ref x, _), | |
828 | List::Cons(ref y, _)) => Some(y, x) | |
829 | } | |
830 | } | |
831 | ~~~~ | |
832 | ||
833 | # A Slightly Longer Example | |
834 | ||
835 | ## You May Find Yourself Living in a Shotgun Shack | |
836 | ||
837 | ~~~~{.rust} | |
838 | fn polycephaly<'l, 'r, T>(left: &'l List<T>, | |
839 | right: &'r List<T>) | |
840 | -> Option<(&'r T, &'l T)> { | |
841 | match *left { | |
842 | List::Cons(ref x, _) => match *right { | |
843 | List::Cons(ref y, _) => Some((y, x)), | |
844 | _ => None, | |
845 | }, | |
846 | _ => None, | |
847 | } | |
848 | } | |
849 | ~~~~ |