gdritter repos rust-examples / 35ed3d5
final state of first presentation Getty Ritter 9 years ago
1 changed file(s) with 434 addition(s) and 121 deletion(s). Collapse all Expand all
11 % The Rust Programming Language
22 % G.D. Ritter
3 % May 2015
3 % June 2015
44
55 # The Rust Programming Language
66
4141
4242 ## Example Program
4343
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
5757
5858 # Systems Programming Languages
5959
166166 ## Rust
167167
168168 ~~~~{.rust}
169 #[derive(Debug,Clone,Copy)]
169170 struct Point { x: isize, y: isize }
170171
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 }
176174 }
177175
178176 fn main() {
179177 let a = Point { x: 1, y: 2 };
180178 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 ~~~~
191182
192183 # What Makes Rust Interesting
193184
197188 \includegraphics[width=.9\textwidth]{imgs/dawkins-owned.png}
198189 \end{center}
199190
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 # Brief Aside
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
213260 ## Traits
214261
215262 ~~~~{.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
228277 ## Traits
229278
230279 ~~~~{.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 print_eq<A: Eq + ToString>(left: A, right: A) {
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) {
258314 if left == right {
259 println!("{} and {} are equal",
260 left.to_string(),
261 right.to_string());
315 println!("these are equal:");
316 left.say();
317 right.say();
262318 } 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 fn ne(&self, other: &Rhs) -> bool;
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;
278334 }
279335
280336 /* 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 {
291347 fn eq(&self, other: &MyNum) -> bool {
292348 self.num == other.num
293349 }
296352 impl Eq for MyNum { }
297353 ~~~~
298354
299 # Brief Aside
300 ## Traits
355 # Preliminary Four
356 ## Implementing Built-In Traits Automatically
301357
302358 ~~~~{.rust}
303359 /* or just this */
305361 struct MyNum { num: i32 }
306362 ~~~~
307363
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
310379 ## Ownership
311380
312381 ~~~~{.rust}
315384
316385 fn main() {
317386 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 };
318403 let y = x;
319404 println!("x = {:?}", x);
320
405 /* doesn't compile */
321406 }
322407 ~~~~
323408
349434 let x = MyNum { num: 2 };
350435 let y = x;
351436 println!("x = {:?}", x);
352 /* so this does not compile */
437 /* so it does not live until the print */
353438 }
354439 ~~~~
355440
363448
364449 fn main() {
365450 let x = MyNum { num: 2 };
366 let y = x.clone();
367 println!("x = {:?}", x);
368 /* but this does! */
451 let y = x.clone(); /* explicit clone */
452 println!("x = {:?}", x);
453 /* but this works! */
369454 }
370455 ~~~~
371456
379464
380465 fn main() {
381466 let x = MyNum { num: 2 };
382 let y = x;
467 let y = x; /* implicit copy */
383468 println!("x = {:?}", x);
384469 /* as does this! */
385470 }
403488 let x = MyNum { num: 2 };
404489 println!("x = {:?}", x);
405490 }
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 }
406509 ~~~~
407510
408511 # What Makes Rust Interesting
423526 fn main() {
424527 let x = MyNum { num: 2 };
425528 let y = x.clone();
426 println!("x = {:?}", y);
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 */
427575 }
428576 ~~~~
429577
520668 ## References
521669
522670 ~~~~{.rust}
523 #[derive(Debug,Clone)]
671 #[derive(Debug)]
524672 struct MyNum { num: i32 }
525673
526674 fn some_func(_: &MyNum) {
534682 /* works! */
535683 }
536684 ~~~~
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 ~~~~