Slide 1

Slide 1 text

ʮGo ݴޠͰͭ͘ΔΠϯλϓϦλʯΛ
 Rust ͰҠ২ͯ͠Έͨ ന౔ܛ, Kei Shiratsuchi, @kei_s RustͷLTձ Shinjuku.rs #7, 2019.11.19(Tue)

Slide 2

Slide 2 text

ࣗݾ঺հ • ന౔ɹܛʢγϥπνɹέΠʣ@kei_s • גࣜձࣾϨτϦό • ࣗવݴޠॲཧɺԻ੠ೝࣝɺػցֶश • ੢৽॓ • ʮձࣾର߅ͷͲࣗຫେձʯͰ༗໊ͳ৽॓ࡾҪϏϧ • Ruby on Rails / JavaScript / Python / Elixir • Rust ͸ࠓճॳΊͯ৮ͬͨʢͷͰɺποίϛ׻ܴ…ʣ

Slide 3

Slide 3 text

ϨτϦόηϛφʔ • ฐࣾͰ݄Ұճ։࠵͍ͯ͠Δࣾ֎ެ ։ηϛφʔ • ൃදΛ YouTube Ͱ࿥ը഑৴ • ࠓճͷ࿩Λ1͔͚࣌ؒͯઆ໌͍ͯ͠ ΔͷͰɺڵຯ͕͋Ε͹ͪ͜Β΋Ͳ ͏ͧ • https://www.youtube.com/watch?v=zdq1lUo7b-I

Slide 4

Slide 4 text

֓ཁ

Slide 5

Slide 5 text

֓ཁ • ʰGo ݴޠͰ࡞ΔΠϯλϓϦλʱ • https://www.oreilly.co.jp/books/9784873118222/ • ΛɺRust Ͱ࠶ݱ͢Δ • https://github.com/kei-s/waiir • Write An Interpreter In Rust • ຊฤɺ෇࿥(ϚΫϩγεςϜ)Λ׬ྃ • ίϛοτίϝϯτʹ೔هΛॻ͍ͨ

Slide 6

Slide 6 text

Go ݴޠͰͭ͘ΔΠϯλϓϦλ

Slide 7

Slide 7 text

Go ݴޠͰͭ͘ΔΠϯλϓϦλ • ΦϦδφϧͷϓϩάϥϛϯάݴޠͷΠϯλϓϦλΛɺGo ͰΠν͔ Βͭ͘Δ • ֎෦ϥΠϒϥϦΛ࢖༻͠ͳ͍ • ϓϩάϥϜʢจࣈྻʣ →
 → ࣈ۟ղੳ →ʢτʔΫϯྻʣ→
 → ߏจղੳ →ʢந৅ߏจ໦ʣ→
 → ධՁ →ʢ࣮ߦ݁Ռʣ

Slide 8

Slide 8 text

ࠓճ࡞Δݴޠ “Monkey” • Cݴޠ෩ͷߏจ • ม਺ଋറ • ੔਺ͱਅِ஋ • ࢉज़ࣜ • จࣈྻσʔλܕ • ഑ྻσʔλܕ • ϋογϡσʔλܕ • ؔ਺ • let age = 1; let name = "Monkey"; let result = 10 * (20 / 2); let myArray = [1, 2, 3, 4, 5]; let myHash = {"name": ”Hi", "age": 28}; myArray[0] // => 1 myHash["name"] // => ”Hi" let add = fn(a, b) { return a + b; }; let add = fn(a, b) { a + b; }; add(1, 2);

Slide 9

Slide 9 text

ࠓճ࡞Δݴޠ “Monkey” let twice = fn(f, x) { return f(f(x)); }; let addTwo = fn(x) { return x + 2; }; twice(addTwo, 2); // => 6 let fibonacci = fn(x) { if (x == 0) { 0 } else { if (x == 1) { 1 } else { fibonacci(x - 1) + fibonacci(x - 2); } } }; • Ϋϩʔδϟ • ؔ਺ͷ࠶ؼݺͼग़͠ • ୈҰڃͷߴ֊ؔ਺ •

Slide 10

Slide 10 text

σϞ • cargo build --release ͯ͠ target/release/waiir Ͱ REPL ىಈ • ΋͘͠͸ cargo run • ෳ਺ߦΛड͚෇͚ΒΕͳ͍ͷͰ஫ҙ •

Slide 11

Slide 11 text

Go ͔Β Rust ΁

Slide 12

Slide 12 text

Go ͔Β Rust ΁ • ͠ΜͲ͔ͬͨͱ͜Ζ 2. nil Λฦͤͳ͍ 3. ΠϯλʔϑΣʔε͔Β࣮ମΛऔΕͳ͍ 4. ؀ڥͷॴ༗ݖ

Slide 13

Slide 13 text

nil Λฦͤͳ͍ • ະ࣮૷ͷτʔΫϯͷॲཧ Ͱ nil Λฦͯ͠αϘΕͳ͍ • Result ͰΤϥʔΛฦ͢ func (p *Parser) parseStatement() ast.Statement { switch p.curToken.Type { case token.LET: return p.parseLetStatement() default: return nil } } fn parse_statement(&mut self, cur_token: Token) -> Result { Ok( match cur_token.t { TokenType::Let => Statement::LetStatement(self.parse_let_statement()?), _ => return Err(ParseError{message: String::from("not implemented")}) } ) }

Slide 14

Slide 14 text

ΠϯλʔϑΣʔε͔Β࣮ମΛऔΕͳ͍ • Go Ͱ͸ΠϯλʔϑΣʔε͔Β࣮ମΛऔΕΔ • ast.Expression ͱͯ͠౉͖ͬͯͨ exp Λɺast.Boolean Ͱ͋Δ͔ νΣοΫ͍ͯ͠Δ • Rust ͷ trait Ͱ͸ෆՄೳ func testBooleanLiteral(t *testing.T, exp ast.Expression, value bool) bool { bo, ok := exp.(*ast.Boolean) if !ok { t.Errorf("exp not *ast.Boolean. got=%T", exp) return false } …

Slide 15

Slide 15 text

ΠϯλʔϑΣʔε͔Β࣮ମΛऔΕͳ͍ • Enum ͷྻڍࢠʹ࣮ࡍͷσʔλΛ֨ೲ͠ɺύλʔϯϚο νͰ࣮ମΛ࢖͏ enum Expression { Integer(IntegerExpression), Boolean(BooleanExpression), ... } #[test] fn test_boolean_expressions() { ... if let Expression::Boolean(boolean) = &stmt.expression { assert_eq!(boolean.value, *expected); } else { assert!(false, "program.statements[0] is not ast::BooleanExpression") }

Slide 16

Slide 16 text

؀ڥͷॴ༗ݖ • let a = 1; Λอଘ͢ΔͨΊʹɺΩʔ ”a”ɺ஋ Integer(1) ͱͯ͠อଘ͢Δ • ஋Λଋറ͢ΔͨΊͷɺ؀ڥ(Environment)ɻத਎͸ϋογϡϚοϓ type Environment struct { store map[string]Object } func (e *Environment) Get(name string) (Object, bool) { obj, ok := e.store[name] return obj, ok } func (e *Environment) Set(name string, val Object) Object { e.store[name] = val return val }

Slide 17

Slide 17 text

؀ڥͷॴ༗ݖ • ؔ਺͕ఆٛ͞ΕͨΒɺ؀ڥΛؔ਺ΦϒδΣΫτʹ౉͠ ͓ͯ͘ • ࣮ߦ࣌ʹɺͦͷ؀ڥΛݩʹ࣮ߦ͢Δ func Eval(node ast.Node, env *object.Environment) object.Object { ... case *ast.FunctionLiteral: params := node.Parameters body := node.Body return &object.Function{Parameters: params, Env: env, Body: body}

Slide 18

Slide 18 text

؀ڥͷॴ༗ݖ • Rust ൛Ͱ͸࠷ॳɺؔ਺ΦϒδΣΫτ͕࣋ͭ env ͸ clone() ͯ͠౉͍ͯͨ͠ • ͔͠͠࠶ؼؔ਺ͰΤϥʔ • ؔ਺ΦϒδΣΫτ͕࣋ͭ env ʹɺޙ͔Β { “fibonacci”: ؔ਺ΦϒδΣΫτ} Λొ ࿥͠ͳ͍ͱ͍͚ͳ͍ͨΊ impl_eval!(FunctionLiteral => (self, env) { Object::Function(Function { parameters: self.parameters.clone(), body: *self.body.clone(), env: env.clone(), }) }); let fibonacci = fn(x) { ... fibonacci(x - 1) + fibonacci(x - 2); };

Slide 19

Slide 19 text

؀ڥͷॴ༗ݖ • Rc/RefCell Λ࢖ͬͯղܾ͠ ͨ • ಉҰͷ env Λผʑʹॴ ༗ͤ͞ΔͨΊʹ Rc Λ࢖ ͏ • Env ΛมߋͰ͖ΔΑ͏ ʹ RefCell Λ࢖͏ impl Environment { pub fn new() -> Rc> { let store = HashMap::new(); let env = Environment { store, outer: None }; Rc::new(RefCell::new(env)) } } impl_eval!(FunctionLiteral => (self, env) { Object::Function(Function { parameters: self.parameters.clone(), body: *self.body.clone(), env: Rc::clone(&env), }) });

Slide 20

Slide 20 text

·ͱΊ

Slide 21

Slide 21 text

·ͱΊ • Go Ͱ؆୯ʹͰ͖͍ͯͨͱ͜Ζ͕ Rust ͩͱϋϚΔ • ͱͯ΋Α͍ Rust ͷษڧʹͳͬͨʂ • ίϯύΠϧΤϥʔʹಋ͔ΕͯίʔσΟϯά͢Δײ͡

Slide 22

Slide 22 text

ࠓޙ • ஌ࣝෆ଍ͷͨΊɺແବʹ clone() ͯ͠ޡຐԽ͍ͯ͠ΔՕॴ͕͍ͭ͘ ΋͋Δ… • ΍ͬͺΓϥΠϑλΠϜཧղ͠੾Ε͍ͯͳ͍ • HashMap ʹొ࿥ͨ͠ value ͷॴ༗ݖ೉͍͠ • ొ࿥ͨ͠ value Λͦͷ··มߋ͍ͨ͠৔߹Ͳ͏͢Ε͹ྑ͍…? • Rust తʹ៉ྷʹ͢ΔͱɺGo ͰͷΞʔΩςΫνϟ͔Β͔ͳΓဃ཭ ͦ͠͏…