言語組 : 課題候補 ~Rubyの文法を256倍いじって遊ぶ編~ 稲葉 一浩 (k.inaba) www.kmonos.net twitter.com/kinaba 要するに • Ruby のスキャナ や • Ruby のパーサ や • RubyVM へのコンパイラ を改造して、新しい機能を付け加えてみよう! 講師陣から出た案 • 多言語オペレータ • パターンマッチ 例1:多言語オペレータ • Rubyの普通のメソッド class Warable def waru(y) … end end a = Warable.new b = a.waru( a ) # 普通 例1:多言語オペレータ • 特別な記号をメソッド名にすると… class Warable def /(y) … end end a = Warable.new b = a./( a ) # 普通 b = a / a # こう書いても大丈夫! 例1:多言語オペレータ • ところで、 Rubyでは日本語メソッド名もつかえます class わりざん def わる(y) … end end a = わりざん.new b = a.わる( a ) # 普通 【実装】これを作ろう【課題】 • 当然、こういうことがしたいですよね! class わりざん def ÷(y) … end end a = わりざん.new b = a.÷( a ) # 普通 b = a ÷ a # 今はエラー!!!!!!!!!!!!!!!!!! 例1:多言語オペレータ • やること – 0: Rubyのスキャナとパーサの仕組みを把握 • “Rubyソースコード完全解説” の復習 – 1: 「+」「ー」「×」「÷」 演算子を増やしてみる • • • • スキャナの変更??? パーサの変更??? VMへのコンパイラの変更??? ちゃんとした多エンコーディング対応??? 例1:多言語オペレータ • やること:発展編 – もっと汎用に演算子を増やせる仕組を考える • 予約語 operator で宣言する??? • 優先順位や結合方向も汎用に増やすには??? class Fixnum def ☆(y); self + y*y; end end p 12 ☆ 3 # エラー (12.☆(3) はOK) operator ☆ p 12 ☆ 3 # 21 例2: パターンマッチ • 文字列だとこんなことができます def sample(str) case str when /^(.)..$/ # 3文字の文字列なら $1 # 1文字目を返す when /^abc(.)def$/ # (略)なら $1 # 4文字目を返す else; raise “えらー” end end 例2: パターンマッチ • 配列だと? def sample(arr) if arr.size == 3 arr[0] elsif arr.size == 7 && arr[0]==1 && arr[1]==2 && arr[2]==3 && arr[4]==4 && arr[5]==5 && arr[6]==6 arr[3] end end 【実装】これを作ろう【課題】 • 配列でもこんな風に…! def sample(arr) case arr when [x,_,_] # 3要素の配列なら x # 1個目を返す when [1,2,3,x,4,5,6] # (略)なら x # 4個目を返す else; raise “えらー” end end ※注意 • 前のページの例は、今のRubyのparse.yでも 構文解析はできます – 変数xにその時点で入っている値と等しいか 判定が行われる x=6 case [1,2,3,9,4,5,6] #今のRubyで実行できるけど when [1,2,3,x,4,5,6] puts “にゃー” #ここには来ない when [1,2,3,9,4,5,x] puts “わん” #ここに来る end ※注意 • なので(case式をそのまま使うなら)、 たぶんパーサーの変更は不要 • NODE_CASEをコンパイルするコードを 改造する??? 例2:パターンマッチ • やること – 1: 配列パターンマッチ専用のキーワード “match” を追加してみる(パーサの改造) match arr when [x, y ,z] … end – 1’: もしくは面倒なので case 式の意味を 勝手に変えちゃう覚悟を決める case arr when [x, y ,z] … end – 2: 一番簡単な場合。when 1つの場合の実装 • コンパイラの改造???VMの改造??? 例2:パターンマッチ / やること • 3: 複数のwhen。else – match … when [x] … when [x,y] … else … end • 4: *パターン – match … when [x, *xs] … end • 5: ネスト – match … when [[x], y, z] … end • 6: 定数パターン – match … when [“hello”, x, y, 123, :symbol] … end まとめ • Rubyを256倍いじって遊ぶ編 – 多言語オペレータ – パターンマッチ – 他に作ってみたい追加文法がある方はどうぞ!
© Copyright 2024 ExpyDoc