メタプログラミング実践@shokaishinjuku.rb #182013/06/26
•@shokai (しょうかい)•初参加•趣味:料理、glitch、プログラミング•Sinatra派•minitest派
せっかく新宿に来たのだから聖地巡礼しよう!!→ 小屋が見つからない靴が濡れて足痛い
引きこもってコード書いてたらネタが溜まってきたので放出していきたい
メタプログラミングとは
「コードを記述するコード を記述すること」(p.11)
なるほどわからん
実際やってみたらわかった!やってみるの大事
今日はメタプログラミングを使って実装してみた3つのGemをご紹介いたします
% gem install skypeSkype Desktop APIのラッパーMac/Linux対応https://github.com/shokai/skype-rubymethod_missingを使用
require rubygemsrequire skype# チャットSkype.message("shokaishokai", "電話かけます")# 電話Skype.call("shokaishokai")call関数やmessage関数はg...
module Skypedef self.method_missing(name, *args)self.exec "#{name.upcase} #{args.join( )}"endendmethod_missingSkype Deskto...
• method_missingはAPIのラッパーを作るのに便利• (APIに規則性がある場合のみ)• API側が変わっても、gemを修正する必要がない• 例:”CALL shokaishokai” が “CALLTO shokaishokai...
% gem install babascriptコンピュータが得意な事はコンピュータが、人間が得意な事は馬場くん  がやってくれる言語https://github.com/masuilab/babascriptinstance_eval, me...
% baba -e アイス買ってきて("#{rand 5}本")baba -e ’コード’もしくはbaba ファイル名
結果
#!/usr/bin/env babaif 0 < Time.now.hour and Time.now.hour < 5もう寝ろ!!else意識を高めてコードを書こう!endwake-up.bb% baba wake-up.bb実行ただのRu...
class Foodef initialize@name = "bar"endendfoo = Foo.newfoo.instance_eval doputs @name # => "bar"endinstance_evalbabaコマンドの中...
module BabaScriptclass Babadef self.method_missing(name, *args)## (略) Androidにnameとargsを送信するendendendRubyの関数名には日本語が使える→ me...
• instance_eval + method_missingで言語が歪む• エラーメッセージがわかりにくくなるので、何でもかんでもinstance_evalするとコード追えなくなる• rspecなど、英語っぽいDSLで書けるgemで使われて...
人間を関数のように扱えるようになるスマホアプリ+人間に命令を送る構文を追加したプログラム言語→ 人間とプログラム言語の新しい関係
% gem install event_emitter全てのクラス/インスタンスにイベント機能を追加できるhttps://github.com/shokai/event_emittermix-in, instance_evalを使用(これメタプ...
class Crawlerinclude EventEmitterdef start(urls)Thread.new dourls.each do |url|beginemit :get, url, HTTParty.get(url).body...
class Fooinclude EventEmitterendclass宣言時にinclude → instance全てにイベント機能が付くEventEmitter.apply Timeclassにapply → class methodとし...
module EventEmitterdef self.included(klass)klass.__send__ :include, InstanceMethodsenddef self.apply(object)object.extend ...
• なぜincludedで受けてもう一度includeを呼んでいるか?というと• gemのネームスペース直下をそのままincludeさせるのが嫌だった• 子moduleに機能を集約したい
メソッドが増えているmix-in前後を比較
• included関数でincludeを受け止めて、複数includeしちゃう事も可能• 動物とか犬とか人間とかの階層分けオブジェクト指向ではなく、機能レベルでの抽象化に向いてる気がする• Sinatraのプラグイン機構に使われている• Ev...
Sinatra::RocketIOでも使っているSinatraでNode.jsのSocket.IOのような事ができるRubygemwebsocket/comet対応
おわり
質問などあれば•@shokai•お気軽に•お声かけください
Upcoming SlideShare
Loading in …5
×

メタプログラミング実践 - shinjuku.rb #18

2,155 views

Published on

shinjuku.rb #18で発表しました

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,155
On SlideShare
0
From Embeds
0
Number of Embeds
551
Actions
Shares
0
Downloads
8
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

メタプログラミング実践 - shinjuku.rb #18

  1. 1. メタプログラミング実践@shokaishinjuku.rb #182013/06/26
  2. 2. •@shokai (しょうかい)•初参加•趣味:料理、glitch、プログラミング•Sinatra派•minitest派
  3. 3. せっかく新宿に来たのだから聖地巡礼しよう!!→ 小屋が見つからない靴が濡れて足痛い
  4. 4. 引きこもってコード書いてたらネタが溜まってきたので放出していきたい
  5. 5. メタプログラミングとは
  6. 6. 「コードを記述するコード を記述すること」(p.11)
  7. 7. なるほどわからん
  8. 8. 実際やってみたらわかった!やってみるの大事
  9. 9. 今日はメタプログラミングを使って実装してみた3つのGemをご紹介いたします
  10. 10. % gem install skypeSkype Desktop APIのラッパーMac/Linux対応https://github.com/shokai/skype-rubymethod_missingを使用
  11. 11. require rubygemsrequire skype# チャットSkype.message("shokaishokai", "電話かけます")# 電話Skype.call("shokaishokai")call関数やmessage関数はgem内に実装されていないしかしなぜか呼び出せる
  12. 12. module Skypedef self.method_missing(name, *args)self.exec "#{name.upcase} #{args.join( )}"endendmethod_missingSkype Desktop API"CALL shokaishokai""MESSAGE shokaishokai こんにちは"Query文字列をSkype.appに送るだけの簡単仕様実装されていない関数の呼び出しを受け取る関数Skype.execの中身はMac/Linux別々に実装
  13. 13. • method_missingはAPIのラッパーを作るのに便利• (APIに規則性がある場合のみ)• API側が変わっても、gemを修正する必要がない• 例:”CALL shokaishokai” が “CALLTO shokaishokai”に仕様変更されても、Skype.callto “shokaishokai” で呼び出せる• Twitter gem等でも使われている
  14. 14. % gem install babascriptコンピュータが得意な事はコンピュータが、人間が得意な事は馬場くん  がやってくれる言語https://github.com/masuilab/babascriptinstance_eval, method_missingを使用@takumibaba
  15. 15. % baba -e アイス買ってきて("#{rand 5}本")baba -e ’コード’もしくはbaba ファイル名
  16. 16. 結果
  17. 17. #!/usr/bin/env babaif 0 < Time.now.hour and Time.now.hour < 5もう寝ろ!!else意識を高めてコードを書こう!endwake-up.bb% baba wake-up.bb実行ただのRuby…ではなく日本語で書いた部分を馬場君が実行してくれる
  18. 18. class Foodef initialize@name = "bar"endendfoo = Foo.newfoo.instance_eval doputs @name # => "bar"endinstance_evalbabaコマンドの中身 = instance_evalFile.open(fname) do |f|BabaScript::Baba.instance_eval f.readendコードやブロックをそのインスタンスのコンテキストで実行するfooのコンテキストで実行されるのでアクセサが無いプロパティ@nameも読める
  19. 19. module BabaScriptclass Babadef self.method_missing(name, *args)## (略) Androidにnameとargsを送信するendendendRubyの関数名には日本語が使える→ method_missingで全部取れるFile.open(fname) do |f|BabaScript::Baba.instance_eval f.readend
  20. 20. • instance_eval + method_missingで言語が歪む• エラーメッセージがわかりにくくなるので、何でもかんでもinstance_evalするとコード追えなくなる• rspecなど、英語っぽいDSLで書けるgemで使われているはず
  21. 21. 人間を関数のように扱えるようになるスマホアプリ+人間に命令を送る構文を追加したプログラム言語→ 人間とプログラム言語の新しい関係
  22. 22. % gem install event_emitter全てのクラス/インスタンスにイベント機能を追加できるhttps://github.com/shokai/event_emittermix-in, instance_evalを使用(これメタプログラミングじゃない気がする!)
  23. 23. class Crawlerinclude EventEmitterdef start(urls)Thread.new dourls.each do |url|beginemit :get, url, HTTParty.get(url).bodyrescue => eemit :error, url, eendemit :completeendendendendcrawler = Crawler.newcrawler.once :error do |err|STDERR.puts eexit 1endcrawler.on :get do |url, page_data|puts "page #{url} get!!"puts page_dataendcrawler.start ["http://shokai.org", "http://example.com", "http://github.com"]mix-inイベント発行イベント受信
  24. 24. class Fooinclude EventEmitterendclass宣言時にinclude → instance全てにイベント機能が付くEventEmitter.apply Timeclassにapply → class methodとしてイベント機能が付くnow = Time.nowEventEmitter.apply nowinstanceにapply → そのinstanceだけにイベント機能が付く(特異メソッド)全てのオブジェクトにイベント機能を追加できる非同期プログラミングに大変便利
  25. 25. module EventEmitterdef self.included(klass)klass.__send__ :include, InstanceMethodsenddef self.apply(object)object.extend InstanceMethodsendmodule InstanceMethodsdef __events@__events ||= []enddef on(type, params={}, &block)## 略enddef emit(type, *data)## 略endendendincludeされた時に呼び出される特異メソッド注入用module内のインスタンスメソッドとプロパティが注入されるprivate methodを強引に呼ぶ
  26. 26. • なぜincludedで受けてもう一度includeを呼んでいるか?というと• gemのネームスペース直下をそのままincludeさせるのが嫌だった• 子moduleに機能を集約したい
  27. 27. メソッドが増えているmix-in前後を比較
  28. 28. • included関数でincludeを受け止めて、複数includeしちゃう事も可能• 動物とか犬とか人間とかの階層分けオブジェクト指向ではなく、機能レベルでの抽象化に向いてる気がする• Sinatraのプラグイン機構に使われている• EventEmitterはブラウザ用JavaScript版もありますhttps://github.com/shokai/event_emitter.js
  29. 29. Sinatra::RocketIOでも使っているSinatraでNode.jsのSocket.IOのような事ができるRubygemwebsocket/comet対応
  30. 30. おわり
  31. 31. 質問などあれば•@shokai•お気軽に•お声かけください

×