Slide 1

Slide 1 text

Ϋϩʔδϟʹ͍ͭͯ Rust ͷ LT ձʂ Rust ೖ໳ऀͷू͍ थԼູ 2017/03/01 1 / 22

Slide 2

Slide 2 text

ࣗݾ঺հ ͳ·͑ थԼູ twitter @trigott ॴଐ KLab inc. ޷͖ͳݴޠ Agda, OCaml 2 / 22

Slide 3

Slide 3 text

▶ Rust ྺ͸΄Μͷগ͠ ▶ ΋ͱ΋ͱܕͷڧ͍ؔ਺ܕݴޠ͕޷͖Ͱɺܕਪ࿦΍ύλʔϯ Ϛονͷ࢖͑Δ Rust ͸ͳΜͱͳ͘࢖͑ͨ ▶ ҰํͰ Rust ͷγεςϜϓϩάϥϛϯάݴޠͱͯ͠ͷʁ੍໿ ʹͿ͔ͭΔ͜ͱ΋͋ͬͨ ▶ Ϋϩʔδϟ͸ؔ਺ܕݴޠͰ͸ೃછΈͷਂ͍֓೦͕ͩɺRust Ͱ ࢖͏ࡍʹ͸஫ҙ͕ඞཁͱ͍͏యܕతͳྫͩͱײͨ͡ͷͰɺΫ ϩʔδϟͷ࿩Λ͠·͢ ▶ Rust ͸ૉਓͳͷͰ࿩͸͍͚ٙͬͯͨͩΔͱ 3 / 22

Slide 4

Slide 4 text

Ϋϩʔδϟͱ͸ ▶ ؔ਺ͱؔ਺தʹݱΕΔม਺ΛධՁ͢ΔͨΊͷ؀ڥͷ૊ ▶ SICP ͷۜߦޱ࠲ͷྫ (define (make-withdraw balance) (lambda (amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient␣funds")))) (define W1 (make-withdraw 100)) (define W2 (make-withdraw 100)) (W1 10) ; => 90 (W1 20) ; => 70 (W1 80) ; => "Insufficient funds" (W2 40) ; => 60 4 / 22

Slide 5

Slide 5 text

▶ OCaml ͷ৔߹ɺࢀর͚ͩѻ͍Λม͑ͯޙ͸΄΅ͦͷ·· let make_withdraw (balance : int ref) : int -> result = fun amount -> if !balance >= amount then (balance := !balance - amount; Ok !balance) else Err "Insufficient␣funds" let () = let w1 = make_withdraw (ref 100) and w2 = make_withdraw (ref 100) in print_result (w1 10); (* Ok (90) *) print_result (w1 20); (* Ok (70) *) print_result (w1 80); (* Err(" Insufficient funds ") * print_result (w2 40) (* Ok (60) *) 5 / 22

Slide 6

Slide 6 text

▶ Rust ͷ৔߹ fn make_withdraw(mut balance: i32) -> Box Result > { Box::new(move |amount: i32| { if balance >= amount { balance -= amount; Ok(balance) } else { Err("Insufficient␣funds") } }) } let mut w1 = make_withdraw (100); let mut w2 = make_withdraw (100); println !("{:?}", w1 (10)); // Ok (90) println !("{:?}", w1 (20)); // Ok (70) println !("{:?}", w1 (80)); // Err(" Insufficient funds ") println !("{:?}", w2 (40)); // Ok (60) 6 / 22

Slide 7

Slide 7 text

▶ mut, FnMut, move, Box ͬͯԿ ▶ ؆୯ͳύʔπ͔Β࢝Ίͯɺઆ໌͍͖ͯ͠·͢ 7 / 22

Slide 8

Slide 8 text

▶ ؆୯ͳؔ਺Λฦͯ͠ΈΔ fn id_i32 () -> i32 -> i32 { |x: i32| { x } } ▶ ΤϥʔʹͳΔ error: expected one of ‘!‘, ‘(‘, ‘::‘, ‘<‘, ‘where‘, or ‘{‘, found ‘->‘ --> account1.rs:2:24 | 2 | fn id_i32() -> i32 -> i32 { | ^^ ▶ ??? 8 / 22

Slide 9

Slide 9 text

▶ υΩϡϝϯτΛಡΉͱɺΫϩʔδϟͷܕ͸ Fn ͱ͍͏ trait Λ ࣮૷͍ͯ͠ͳ͍ͱ͍͚ͳ͍Β͍͠ ▶ ͳΜ͔Τϥʔϝοηʔδෆ਌੾ͳؾ͕ ▶ ͱΓ͋͑ͣงғؾͰԼͷΑ͏ʹॻ͍ͯΈΔ fn id_i32 () -> Fn(i32) -> i32 { |x: i32| { x } } ▶ ΤϥʔʹͳΔ error[E0308]: mismatched types --> account1.rs:7:9 | 7 | |x: i32| { x } | ^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure | = note: expected type ‘std::ops::Fn(i32) -> i32 + ’static‘ = note: found type ‘[[email protected]:7:9: 7:23]‘ ▶ ??? 9 / 22

Slide 10

Slide 10 text

▶ Ϋϩʔδϟͷܕ͸ͦΕͧΕݻ༗ͷܕ໊͕ͭͨ͘Ίɺγάχ νϟͷܕͱਪ࿦͞ΕͨܕͱͰϛεϚον͕ى͖͍ͯΔͱࢥΘ ΕΔ ▶ ྫ͑͹ɺҾ਺ͱͯ͠ΫϩʔδϟΛड͚औΔͱ͖͸ɺ generics ʹ trait ੍໿Λ͚ͭΔܗͰܕΛॻ͔ͳ͍ͱ͍͚ ͳ͍ ▶ > Because each closure generates its own environment struct and implementation of Fn and friends, these types are anonymous. They exist solely for this closure. So Rust shows them as closure@, rather than some autogenerated name. ▶ ΫϩʔδϟΛฦ͍ͨ͠৔߹Ͳ͏ͨ͠Β͍͍͔෼͔Βͣ... 10 / 22

Slide 11

Slide 11 text

▶ ࣮͸΋͏ҰͭΤϥʔ͕ग़͍ͯͨͷͰͦͪΒʹ஫໨ͯ͠ΈΔ error[E0277]: the trait bound ‘std::ops::Fn(i32) -> i32 + ’static: std::marker::Sized‘ is not satisfied --> account1.rs:6:20 | 6 | fn id_i32() -> Fn(i32) -> i32{ | ^^^^^^^^^^^^^^ | the trait ‘std::marker::Sized‘ is not implemented for | ‘std::ops::Fn(i32) -> i32 + ’static‘ | = note: ‘std::ops::Fn(i32) -> i32 + ’static‘ does not have a constant size known at compile-time = note: the return type of a function must have a statically known size ▶ Fn(i32) -> i32 ͸ trait ͳͷͰɺෳ਺ͷܕͷީิ͕͋Γɺ ܕͷαΠζ͕෼͔Βͳ͍ ▶ ฦΓ஋ͷܕͷαΠζ͸ίϯύΠϧ࣌ʹ෼͔͍ͬͯΔඞཁ͕͋ ΔͨΊɺౖΒΕ͍ͯΔ 11 / 22

Slide 12

Slide 12 text

▶ Box Λ࢖͏ ▶ ώʔϓྖҬ΁ͷϙΠϯλܕ ▶ ࢀরͳͷͰܕͷαΠζ͸Ұఆ fn id_i32 () -> Box i32 > { Box::new(|x: i32| { x }) } ▶ Ͱ͖ͨ! ▶ ͳ͔ͥܕνΣ οΫ௨Δ 12 / 22

Slide 13

Slide 13 text

▶ ͦΖͦΖ mut ͍ͨ͠ ▶ Rust ͷม਺͸جຊ immutableɺՄมʹ͍ͨ͠ͱ͖͸ mut Λ͚ͭΔ fn make_adder () -> Box i32 > { let mut acc = 0; Box::new(|x: i32| { acc += x; acc }) } 13 / 22

Slide 14

Slide 14 text

▶ ΤϥʔʹͳΔ error[E0373]: closure may outlive the current function, but it borrows ‘acc‘, which is owned by the current function --> account1.rs:16:18 | 16 | Box::new(|x: i32| { | ^^^^^^^^ may outlive borrowed value ‘acc‘ 17 | acc += x; | --- ‘acc‘ is borrowed here | ▶ ΢ΦΞΞΞΞΞΞΞ 14 / 22

Slide 15

Slide 15 text

▶ ߟ͑ͯΈΑ͏ fn make_adder () -> Box i32 > { let mut acc = 0; Box::new(|x: i32| { acc += x; acc }) } let mut adder = make_adder () println !("{:?}", adder (10)) ▶ acc ͷ lifetime ͸ make_adder ͷத਎͚ͩ ▶ make_adder ͷฦ͢Ϋϩʔδϟ͸ make_adder ͷຊମΑΓ΋ ௕ੜ͖͢Δ ▶ make_adder ͷฦ͢Ϋϩʔδϟ͸ acc Λࢀর͍ͯ͠Δ͕ make_adder ͷ࣮ߦ͕ऴΘͬͨ͋ͱͩͱ͢Ͱʹ acc ͸ࢮΜͰ ͍ΔͨΊࢀরͰ͖ͳ͍ 15 / 22

Slide 16

Slide 16 text

help: to force the closure to take ownership of ‘acc‘ (and any other referenced variables), use the ‘move‘ keyword, as shown: | Box::new(move |x: i32| { ▶ ࣮͸ help ͕ग़͍ͯͨͷͰɺͦΕʹै͍ move Λ࢖͏ ▶ move Λ࢖͏ͱ؀ڥதͷม਺ͷॴ༗ݖΛऔಘ͢Δ ▶ Ϋϩʔδϟʹ৽͘͠؀ڥΛ༩͑Δͱ΋ߟ͑ΒΕΔ ▶ ؀ڥͷ࡞੒Λ໌ࣔ͢Δඞཁ͕͋Δ fn make_adder () -> Box i32 > { let mut acc = 0; Box::new(move |x: i32| { acc += x; acc }) } ▶ acc ͷॴ༗ݖ͕Ϋϩʔδϟͷத਎ʹҠৡ͞ΕΔͷͰɺΫϩʔ δϟͱ acc ͷ lifetime ͕Ұக͢Δ 16 / 22

Slide 17

Slide 17 text

▶ ͱ͜ΖͰΤϥʔͰ͢ error: cannot assign to captured outer variable in an ‘Fn‘ closure --> account1.rs:25:13 | 25 | acc += x; | ^^^^^^^^ | 17 / 22

Slide 18

Slide 18 text

fn make_adder () -> Box i32 > { let mut acc = 0; Box::new(move |x: i32| { acc += x; acc }) } ▶ Fn ͱ͍͏ trait ͸؀ڥதͷม਺Λมߋ͢Δ͜ͱ͕Ͱ͖ͳ͍ ▶ มߋ͍ͨ͠৔߹ FnMut Λ࢖͏ඞཁ͕͋Δ 18 / 22

Slide 19

Slide 19 text

Fn ʹ͍ͭͯগ͠ৄࡉ ▶ Fn ͱ͍͏ trait ͸ʮ࣮ߦ͢Δʯͱ͍͏ϝιουΛ࣮૷͢Δ͜ ͱΛཁٻ͍ͯ͠Δ pub trait Fn : FnMut { extern "rust -call" fn call (&self , args: Args) -> Self :: Output; } ▶ &self ͱͯ͠ΫϩʔδϟຊମΛड͚औ͍ͬͯΔ͜ͱʹ஫ҙ ▶ ͨͩͷࢀরͳͷͰɺมߋͰ͖ͳ͍ ▶ FnMut ͷ৔߹ɺ&mut self ͱͯ͠ΫϩʔδϟΛड͚औͬͯ ͍ΔͨΊɺ؀ڥΛมߋ͢Δ͜ͱ͕Մೳ pub trait FnMut : FnOnce { extern "rust -call" fn call_mut (&mut self , args: Args) -> Self :: Output; } 19 / 22

Slide 20

Slide 20 text

▶ ॳظ஋͸ͦͷ··ड͚औΔ ▶ make_adder ͷฦΓ஋͸ mut Ͱͳ͍ͱ͍͚ͳ͍͜ͱʹ஫ҙ fn make_adder(init: i32) -> Box i32 > { let mut acc = init; Box::new(move |x: i32| { acc += x; acc }) } let mut adder = make_adder (10); println !("{:?}", adder (10)); 20 / 22

Slide 21

Slide 21 text

▶ ͱ͍͏Θ͚Ͱ׬੒ʢ࠶ܝʣ fn make_withdraw(mut balance: i32) -> Box Result > { Box::new(move |amount: i32| { if balance >= amount { balance -= amount; Ok(balance) } else { Err("Insufficient␣funds") } }) } let mut w1 = make_withdraw (100); let mut w2 = make_withdraw (100); println !("{:?}", w1 (10)); // Ok (90) println !("{:?}", w1 (20)); // Ok (70) println !("{:?}", w1 (80)); // Err(" Insufficient funds ") println !("{:?}", w2 (40)); // Ok (60) 21 / 22

Slide 22

Slide 22 text

ײ૝ ▶ Ϋϩʔδϟ+mut ͷ߹ΘٕͤͰϋϚΓͲ͜Ζ͕͔ͳΓ૿͑ͨ ҹ৅ ▶ ࢀߟʹ͢Δ΋ͷ͸ The Rust Programming Language ͚ͩͰ ΋ཧղͰ͖Δ ▶ help ͸ศར͚ͩͲͪΌΜͱߟ͑ͨ΄͏͕͍͍ ▶ ͦͷ΄͏͕໘ന͍ 22 / 22