@emasaka
自己紹介●   @emasaka●   本名:高橋正和●   40代 フリーター●   ブログ    「本を読む」http://emasaka.blog65.fc2.com/●   代表作:Bash on Rails
近況
nagaino作りました●   複数の短縮URLを1リクエストで多段展開する    Web APIサービス                    http://nagaino.herokuapp.com/
今日の話
Perl
Perlのソースフィルタ●   ソースを読み込んでからパースするまでの間    に、スクリプトからソースを直接いじれる
Filter::SQL●   Perlのソース中にインラインでSQL文を埋め    込む●   奥一穂氏作
どっちかというとAcme(ネタ系)モジュールで    使われる
Acme::Bleach●   自分を読みんでいるソースファイルを書き換え    て、空白とタブだけにしてしまう●   (でも実行できる)
Acme::Brainfuck●   Perlのソース中にインラインでBrainf*ckを埋    め込む
Acme::W●   Perlの識別子を草だらけにする    ●   print → WWwwWW
Acme::Metification●   ソース中に“meta 2, 5”と書くと、その行が、    2〜5行目の内容に置きかわる    ●   指定範囲に自分が入っていると無限再帰●   “recursemeta depth => 10, ...
Rubyで(超簡易版)ソースフィルタ
Rubyのソースにパッチ●   ruby.cのload_file_internal()
diff ­up ruby­1.9.2­p290/ruby.c filter­ruby­1.9.2­p290/ruby.c­­­ ruby­1.9.2­p290/ruby.c      2010­12­23 19:49:13.000000000...
内容●   source_filterメソッドが定義されていれば    ●   ファイルの内容をStringに読み込む    ●   source_filterに通す    ●   結果をパース●   定義されていなければいつも通り
利用例
例1「Rubyのメソッド呼び出しが“.”なのは直感に     反する。    “->”に」
フィルタ(arrow.rb)def source_filter(str)  str.gsub(/­>/, .)end
サンプル(arrow_sample.rb)[3, 5, 7]­>map {|i| i + 2 }­>each do |i|  puts i­>to_send
実行$ ruby ­rarrow arrow_sample.rb579              コマンドライン              で直接指定
例2:さらに●   “$”“{”を無視●   “}”を“end”に●   “function”を“def”に●   “this”を“self”に
フィルタ(arrow2.rb)def source_filter(str)  str.gsub(/­>/, .).gsub(/}/, end).    gsub(/function/, def).    gsub(/this/, self). ...
サンプル(arrow2_sample.rb)class Hoge {  function foo() {    puts($this­>class());    return $this;  }}Hoge­>new­>foo();
実行$ ruby ­rarrow2 arrow2_sample.rbHoge
例3「Rubyはrequireとinclude     が混乱する」
フィルタ(include.rb)def source_filter(str)  str.gsub(/^s*#s*includes+<(.[^>]*)>$/,           require "1" )end
サンプル(include_sample.rb)#include <uri>u = URI.parse("http://example.com:80/hoge?fuga#foo")p u
実行$ ruby ­rinclude include_sample.rb#<URI::HTTP:0x8463c84 URL:http://example.com/hoge?fuga#foo>
例4“ennnnnd”で5レベル まとめてendしたい
サンプル(ennd_sample.rb)module MyModule  class MyClass    def my_method      10.times do |i|        if (i % 2) == 0          p...
フィルタ(ennd.rb)def source_filter(str)  str.gsub(/e(n{2,})d/) do    Array.new($1.length, end).join(;)  endend
実行$ ruby ­rennd ennd_sample.rbevenoddevenoddevenoddevenoddevenodd
例5“end”なしでインデントで      endしたい
すでにendless rubyが  あるのでパス
例6 縦書きでRubyを書く
サンプル(tate_sample.rb)      e           (      n           1      d  e     i  .         n     f  .         d  p     2       ...
フィルタ(tate.rb)def source_filter(str)  str.split(/n/).inject([]) {|r, s|    s.each_char.with_index do |c, i|      r[i] = r[i...
実行$ ruby ­rtate tate_sample.rb2468101214161820
例7スペースとタブで Rubyを書く
サンプル(bleach_sample.rb)    見えません
フィルタ(bleach.rb)def source_filter(str)  [str.delete("^ t").   tr(" t", 01) ].pack(b*)end
実行$ ruby ­rbleach bleach_sample.rbHello, World!
例8  見えないとつまらないので“ダァシエリイェス!!”で   Rubyを書く
サンプル(kq_sample.rb)ダァダァダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァシエリイェス!!ダァシエリイェス!!ダァシエリイェス!!シエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!ダァシエリイェス!!シエ...
フィルタ(kq.rb)# ­*­ coding: utf­8 ­*­def source_filter(str)  [str.force_encoding(Encoding::UTF_8).   scan(/ダァ|シエリイェス!!/).   m...
実行$ ruby ­rkq kq_sample.rbHello, World!
終
Upcoming SlideShare
Loading in …5
×

メタメタプログラミングRuby

1,190 views

Published on

NOTE: These are joke programs

Published in: Art & Photos
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,190
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

メタメタプログラミングRuby

  1. 1. @emasaka
  2. 2. 自己紹介● @emasaka● 本名:高橋正和● 40代 フリーター● ブログ 「本を読む」http://emasaka.blog65.fc2.com/● 代表作:Bash on Rails
  3. 3. 近況
  4. 4. nagaino作りました● 複数の短縮URLを1リクエストで多段展開する Web APIサービス http://nagaino.herokuapp.com/
  5. 5. 今日の話
  6. 6. Perl
  7. 7. Perlのソースフィルタ● ソースを読み込んでからパースするまでの間 に、スクリプトからソースを直接いじれる
  8. 8. Filter::SQL● Perlのソース中にインラインでSQL文を埋め 込む● 奥一穂氏作
  9. 9. どっちかというとAcme(ネタ系)モジュールで 使われる
  10. 10. Acme::Bleach● 自分を読みんでいるソースファイルを書き換え て、空白とタブだけにしてしまう● (でも実行できる)
  11. 11. Acme::Brainfuck● Perlのソース中にインラインでBrainf*ckを埋 め込む
  12. 12. Acme::W● Perlの識別子を草だらけにする ● print → WWwwWW
  13. 13. Acme::Metification● ソース中に“meta 2, 5”と書くと、その行が、 2〜5行目の内容に置きかわる ● 指定範囲に自分が入っていると無限再帰● “recursemeta depth => 10, 2, 5”と書くと、 10レベルまで再帰
  14. 14. Rubyで(超簡易版)ソースフィルタ
  15. 15. Rubyのソースにパッチ● ruby.cのload_file_internal()
  16. 16. diff ­up ruby­1.9.2­p290/ruby.c filter­ruby­1.9.2­p290/ruby.c­­­ ruby­1.9.2­p290/ruby.c      2010­12­23 19:49:13.000000000 +0900+++ filter­ruby­1.9.2­p290/ruby.c       2011­10­28 21:50:44.452623054 +0900@@ ­1618,7 +1618,16 @@ load_file_internal(VALUE arg)        return (VALUE)rb_parser_compile_string(parser, fname, f, line_start);     }     rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("­"));­    tree = rb_parser_compile_file(parser, fname, f, line_start);+    {+       VALUE source_filter = rb_intern("source_filter");+       if (rb_obj_respond_to(rb_cObject, source_filter, 1)) {+           VALUE s1 = rb_funcall(f, rb_intern("read"), 0);+           VALUE s2 = rb_funcall(rb_mKernel, source_filter, 1, s1);+           tree = rb_parser_compile_string(parser, fname, s2, line_start);+       } else {+           tree = rb_parser_compile_file(parser, fname, f, line_start);+       }+    }     rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));     if (script && tree && rb_parser_end_seen_p(parser)) {        rb_define_global_const("DATA", f);
  17. 17. 内容● source_filterメソッドが定義されていれば ● ファイルの内容をStringに読み込む ● source_filterに通す ● 結果をパース● 定義されていなければいつも通り
  18. 18. 利用例
  19. 19. 例1「Rubyのメソッド呼び出しが“.”なのは直感に 反する。 “->”に」
  20. 20. フィルタ(arrow.rb)def source_filter(str)  str.gsub(/­>/, .)end
  21. 21. サンプル(arrow_sample.rb)[3, 5, 7]­>map {|i| i + 2 }­>each do |i|  puts i­>to_send
  22. 22. 実行$ ruby ­rarrow arrow_sample.rb579 コマンドライン で直接指定
  23. 23. 例2:さらに● “$”“{”を無視● “}”を“end”に● “function”を“def”に● “this”を“self”に
  24. 24. フィルタ(arrow2.rb)def source_filter(str)  str.gsub(/­>/, .).gsub(/}/, end).    gsub(/function/, def).    gsub(/this/, self).    delete(${)end
  25. 25. サンプル(arrow2_sample.rb)class Hoge {  function foo() {    puts($this­>class());    return $this;  }}Hoge­>new­>foo();
  26. 26. 実行$ ruby ­rarrow2 arrow2_sample.rbHoge
  27. 27. 例3「Rubyはrequireとinclude が混乱する」
  28. 28. フィルタ(include.rb)def source_filter(str)  str.gsub(/^s*#s*includes+<(.[^>]*)>$/,           require "1" )end
  29. 29. サンプル(include_sample.rb)#include <uri>u = URI.parse("http://example.com:80/hoge?fuga#foo")p u
  30. 30. 実行$ ruby ­rinclude include_sample.rb#<URI::HTTP:0x8463c84 URL:http://example.com/hoge?fuga#foo>
  31. 31. 例4“ennnnnd”で5レベル まとめてendしたい
  32. 32. サンプル(ennd_sample.rb)module MyModule  class MyClass    def my_method      10.times do |i|        if (i % 2) == 0          puts even        else          puts odd        ennnnndMyModule::MyClass.new.my_method
  33. 33. フィルタ(ennd.rb)def source_filter(str)  str.gsub(/e(n{2,})d/) do    Array.new($1.length, end).join(;)  endend
  34. 34. 実行$ ruby ­rennd ennd_sample.rbevenoddevenoddevenoddevenoddevenodd
  35. 35. 例5“end”なしでインデントで endしたい
  36. 36. すでにendless rubyが あるのでパス
  37. 37. 例6 縦書きでRubyを書く
  38. 38. サンプル(tate_sample.rb)   e           (   n           1   d  e     i  .      n     f  .      d  p     2         u  (  0         t  i  )         s     .            %  e         i     a            2  c            )  h                            =  d            =  o                            0  |               i               |
  39. 39. フィルタ(tate.rb)def source_filter(str)  str.split(/n/).inject([]) {|r, s|    s.each_char.with_index do |c, i|      r[i] = r[i] ? r[i] + c : c    end    r  }.reverse.join("n")end
  40. 40. 実行$ ruby ­rtate tate_sample.rb2468101214161820
  41. 41. 例7スペースとタブで Rubyを書く
  42. 42. サンプル(bleach_sample.rb) 見えません
  43. 43. フィルタ(bleach.rb)def source_filter(str)  [str.delete("^ t").   tr(" t", 01) ].pack(b*)end
  44. 44. 実行$ ruby ­rbleach bleach_sample.rbHello, World!
  45. 45. 例8 見えないとつまらないので“ダァシエリイェス!!”で Rubyを書く
  46. 46. サンプル(kq_sample.rb)ダァダァダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァシエリイェス!!ダァシエリイェス!!ダァシエリイェス!!シエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!ダァシエリイェス!!シエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!ダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァダァダァダァダァダァシエリイェス!!ダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァダァシエリイェス!!ダァダァダァダァダァシエリイェス!!ダァダァシエリイェス!!ダァシエリイェス!!ダァシエリイェス!!ダァダァシエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!シエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!シエリイェス!!ダァシエリイェス!!ダァダァダァダァダァダァダァシエリイェス!!ダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァシエリイェス!!ダァシエリイェス!!ダァシエリイェス!!シエリイェス!!シエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!ダァダァシエリイェス!!ダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!シエリイェス!!ダァシエリイェス!!シエリイェス!!ダァダァダァシエリイェス!!ダァダァシエリイェス!!シエリイェス!!ダァシエリイェス!!ダァダァダァダァシエリイェス!!ダァダァシエリイェス!!シエリイェス!!シエリイェス!!ダァダァシエリイェス!!ダァダァダァシエリイェス!!ダァシエリイェス!!ダァダァダァダァ
  47. 47. フィルタ(kq.rb)# ­*­ coding: utf­8 ­*­def source_filter(str)  [str.force_encoding(Encoding::UTF_8).   scan(/ダァ|シエリイェス!!/).   map {|s| s == ダァ ? 0 : 1 }.   join() ].pack(b*)end
  48. 48. 実行$ ruby ­rkq kq_sample.rbHello, World!
  49. 49.

×