$30 off During Our Annual Pro Sale. View Details »

Rust で遅延評価を 実装してみる

Linda_pp
June 27, 2017

Rust で遅延評価を 実装してみる

RustのLT会! Rust入門者の集い #3

Linda_pp

June 27, 2017
Tweet

More Decks by Linda_pp

Other Decks in Technology

Transcript

  1. Rust Ͱ஗ԆධՁΛ
    ࣮૷ͯ͠ΈΔ
    RustͷLTձʂ Rustೖ໳ऀͷू͍ #3
    @Linda_pp
    @rhysd

    View Slide

  2. ͋Β͢͡
    • ७ਮؔ਺ܕσʔλߏ଄ΛಡΈͳ͕
    Β Rust Ͱ࣮૷͍ͯͨ͋͠Δ೔ɼ
    ஗ԆධՁΛ࢖͏σʔλߏ଄͕ग़ݱ
    • Rust ͸஗ԆධՁ͡Όͳ͍…
    • ࣮૷ͨ͠ https://goo.gl/qMGuZQ

    View Slide

  3. ஗ԆධՁͱ͸
    ࣜΛ͙͢ʹ͸ධՁͤͣɼඞཁʹͳͬͨ࣌ʹධ
    Ձ͢Δ

    View Slide

  4. ஗Ԇ͠ͳ͍ධՁ
    1 // 1000ݸͷૉ਺Λͭ͘ΔʢΊͬͪΌॏ͍ॲཧʣ
    2 let n = primes1000();
    3
    4 // ...
    5
    6 // 100൪໨දࣔ
    7 println!("{}", vec[99]);
    8
    9 // 1000൪໨දࣔ
    10 println!("{}", vec[999]);

    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  5. ஗ԆධՁ
    1 // lazily! Ͱғ·Εͨࣜ͸஗ԆධՁ͞ΕΔ
    2 // ͜ͷ࣌఺Ͱ͸ vec ͸ܭࢉ͞Ε͍ͯͳ͍
    3 let vec = lazily!{
    4 prime1000th()
    5 };
    6
    7 // vec Λ࢖༻͢ΔλΠϛϯάͰॳΊͯ vec ΛධՁ
    8 println!("{}", vec[99]);
    9
    10 // Ұ౓ධՁͨ݁͠Ռ͸Ωϟογϡ͞Εͯ࢖͍·Θ͞ΕΔ
    11 println!("{}", vec[999]);

    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  6. σʔλͷ࣋ͪํ
    1 // αϯΫɿܭࢉΛද͢σʔλߏ଄
    2 enum Thunk<'a, T: 'a> {
    3 // ·ͩܭࢉ͞Εͯͳ͍ঢ়ଶΛΫϩʔδϟͰ࣋ͭ
    4 NotYet(Box T + 'a>),
    5 // ܭࢉࡁΈ
    6 Memo(T),
    7 }
    8
    9 // ஗Ԇ͞ΕͨࣜΛද͢ߏ଄ମ Delayed
    10 pub struct Delayed<'a, T: 'a> {
    11 thunk: RefCell>>
    12 }

    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  7. σʔλͷ࣋ͪํ
    1 impl<'a, T: 'a> Delayed<'a, T> {
    2 // ৽͍͠஗ԆධՁࣜΛੜ੒
    3 // ΫϩʔδϟΛड͚औͬͯ RefCell ʹಥͬࠐΉ
    4 pub fn new(f: F) -> Self where F: Fn() -> T + 'a {
    5 Delayed { thunk: RefCell::new(
    6 Box::new(
    7 NotYet(Box::new(f))
    8 )
    9 ) }
    10 }
    11 }
    12
    13 // ϚΫϩͰ move Ωϟϓνϟ͢ΔΫϩʔδϟʹల։͢Δ
    14 // lazily!{42} -> Delayed::new(move || { 42 })
    15 #[macro_export]
    16 macro_rules! lazily {
    17 ($($b:tt)+) => {
    18 self::Delayed::new(move || { $($b)+ })
    19 }
    20 }
    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  8. force: ஗Ԇ͞ΕͨࣜΛධՁ
    1 impl<'a, T: 'a> Delayed<'a, T> {
    2 pub fn force(&self) {
    3 // ͜͜Ͱ mut ʹ͠ͳ͍ͱαϯΫ͕ߋ৽Ͱ͖ͳ͍ͷͰɼ
    4 // RefCell ͰแΉ
    5 let mut thunk = &mut *self.thunk.borrow_mut();
    6 let val = match **thunk {
    7 // ະධՁͳΒอ͍࣋ͯͨ͠ΫϩʔδϟΛ࣮ߦ͠ɼ
    8 // ܭࢉΛ࣮ߦ͢Δɽ
    9 NotYet(ref invoke) => {
    10 Box::new(Memo(invoke()))
    11 },
    12 // ͢ͰʹܭࢉࡁΈͳΒԿ΋͠ͳ͍
    13 Memo(_) => return,
    14 };
    15 // ܭࢉͨ͠஋Λ͓࣋ͬͯ͘
    16 *thunk = val;
    17 }
    18 }
    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  9. ஗ԆධՁͷλΠϛϯά
    Rc ͕΍͍ͬͯΔΑ͏ʹɼDerefτϨΠτ
    Λ࢖ͬͯɼϝιουݺͼग़͠ͷλΠϛϯάͰ
    ࣗಈͰத਎͕ධՁ͞ΕΔΑ͏ʹ͢Δ
    1 let s = lazily!("foo".to_string())
    2
    3 // s ͕ࣗಈͰධՁ͞ΕΔ
    4 s.as_str();
    5
    6 // * ԋࢉࢠͰ໌ࣔతʹධՁ΋Ͱ͖Δ
    7 *s;

    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  10. Deref Ͱࢀর࣌ʹࣗಈධՁ
    1 impl<'a, T: 'a> Deref for Delayed<'a, T> {
    2 // T ͕ධՁ݁Ռͷ஋ͷܕ
    3 type Target = T;
    4 fn deref(&self) -> &T {
    5 self.force();
    6 // RefCell ͷத਎ΛҰ࣌తʹऔΓग़͢
    7 let thunk = unsafe {
    8 self.thunk.as_ptr().as_ref().unwrap()
    9 };
    10 match **thunk {
    11 // αϯΫͷத΁ͷࢀরΛฦ͢
    12 Memo(ref v) => v,
    13 _ => unreachable!(),
    14 }
    15 }
    16 }

    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide

  11. ͭͬͨ͘஗ԆධՁͰ஗ԆϦετ
    Λͭͬͨ͘ײ૝
    • ΄΅ॻ੶಺ͷઆ໌௨Γʹίʔυ͕ॻ͚ͯྑ͍ײ͡
    • Deref ͸༧૝֎ͷλΠϛϯάͰܭࢉ͕࣮ߦ͞Εͯ͠·
    ͏͜ͱ͕͋ͬͨɽ
    • Clone Λ࣮૷͢ΔͨΊʹ݁ہ Box Λ Rc ʹ͢Δඞཁ͕
    ͋ͬͨ
    • ϜʔϒΩϟϓνϟͰण໋͕བྷΉͷͰɼlazily! Ͱੜ੒͠
    ͨ஋ͷѻ͍͕Ϝζ͍

    ιʔεɿ https://goo.gl/qMGuZQ

    View Slide