Rubyのメタプログラミングメモ
Classをインスタンス化する時にHashで渡した値でInitializeするクラスのテンプレート
class Person attr_accessor :name, :age, :address def initialize( hash={}) if block_given? yield( self ) else hash.each do |k, v| public_send("#{k}=", v) if respond_to?("#{k}=") end end end def to_s instance_variables.map do |ivar| value = self.send( ivar.to_s.tr("@", "")) "#{ivar}: #{value}" end.join(", ") end end p1 = Person.new({name: "taro", age: 20, address: 'tokyo'}) puts p1 p2 = Person.new do |f| f.name = "jiro" f.age = 30 f.address = "tokyo" end puts p2 class Man < Person end p3 = Man.new do |m| m.name ="saburo" m.age = 30 m.address = "yokohama" end puts p3 p4 = Man.new({name: "shiro", age: 33, address: "oosaka"}) puts p4
クラスマクロ
- 例外用のクラスマクロを定義した親クラスのテンプレート
class ExceptionBase < StandardError @_code def self.code(code=nil) # 引数がnilの時はgetter, nilでない時はsetterになる @_code ||= code end def code self.class.instance_variable_get("@_code") end end class NotFoundException < ExceptionBase code 404 end class ForbiddenException < ExceptionBase code 403 end p NotFoundException.code # => 404 p NotFoundException.new.code #=> 404 p ForbiddenException.code # => 403 p ForbiddenException.new.code # => 403
後で読む
空白で区切って指定したフィールドの文字を取得
$ echo "1 2 3" | cut -d " " -f3 3
■
def check_names names return unless Hash === names invalid_options = names.keys.map { |k| k.to_sym } - [:rdoc, :clobber_rdoc, :rerdoc] unless invalid_options.empty? then raise ArgumentError, "invalid options: #{invalid_options.join ', '}" end end
今日は、rdoc の task.rbを読んだ。これは、名前をチェックするメソッドで、 hashのキーが指定したものだけであることをチェックしている。
Rubyの特殊変数メモ
Classをインスタンス化する時にHashで渡した値でInitializeする
Classをインスタンス化する時にHashで渡した値でInitializeする
class Person attr_accessor :name, :age, :address def initialize( hash={}) if block_given? yield( self ) else hash.each do |k, v| public_send("#{k}=", v) if respond_to?("#{k}=") end end end def to_s instance_variables.map do |ivar| value = self.send( ivar.to_s.tr("@", "")) "#{ivar}: #{value}" end.join(", ") end end p1 = Person.new({name: "taro", age: 20, address: 'tokyo'}) puts p1 p2 = Person.new do |f| f.name = "jiro" f.age = 30 f.address = "tokyo" end puts p2 class Man < Person def initialize(hash={}) super(hash) end end puts Man.new({name: "saburo", age: 25, address: "saitama"})
Hash.newにブロックを渡す
以下の記事を読んで初めて知ったのでメモ。
Ruby で メモ化カッコカリ( #rubytokai 発表メモ) - 名古屋で数学するプログラマ(仮)
Hash.new にブロックを渡すことができる。
このブロックはすぐには実行されずに、h["key"] と言う形で参照されたキーがhash内に存在しない時に 呼ばれる。いわゆる遅延実行。
h = Hash.new do |hash, key| hash[key] = 9999 + 9999 # 思いつかないけど何か時間のかかる処理 end h["a"] p h["a"] # => 19998 p h["a"] # => 19998
これを利用してメモ化を実装できる。