本文へスキップ
BecomeCoder

Rubyコース · 第9章 実務のRuby ― 記法を深める · レッスン41

メタプログラミング入門 ― コードでコードを作る

ブラウザで完結

導入

Ruby は「メソッドを実行時に作る」「呼ばれたメソッドが無くても対応する」といった、プログラムでプログラムを書くことができます。これをメタプログラミングと呼び、Rails の魔法のような書き心地を支えています。入口の2つ、define_methodmethod_missing を触ってみましょう。

説明

define_method は、メソッドを実行時に動的に定義します。似たメソッドをまとめて作れます。

class Calculator
  define_method(:double) { |x| x * 2 }
  define_method(:triple) { |x| x * 3 }
end

c = Calculator.new
puts c.double(5)     # 10
puts c.triple(5)     # 15

method_missing は、存在しないメソッドが呼ばれたときに代わりに実行されます。設定値の取得などを柔軟にさばけます。

class Config
  def initialize
    @data = { host: "localhost", port: 8080 }
  end

  def method_missing(name, *args)
    @data[name] || "未設定"
  end
end

c = Config.new
puts c.host       # localhost(host メソッドは定義していないのに動く)
puts c.port       # 8080
puts c.unknown    # 未設定

メタプログラミングは強力ですが、使いすぎると「どこで定義されたか分からない」読みにくいコードにもなります。まずは仕組みを知ることが、Rails のようなライブラリの中身を理解する助けになります。

やってみよう

define_method で別の計算メソッド(例:half)を足したり、method_missing@data を書き換えて、定義していない名前でも値が返る様子を確かめましょう。

演習

Calc クラスdefine_method(:twice) で「引数を2倍して返す」メソッドを定義してください。Calc.new.twice(5) の結果を puts で表示します(10 になります)。

ヒント1を見る

define_method(:twice) { |x| x * 2 } をクラスの中に書きます。

実際に動かしてみよう

下のエディタにRubyを書いて「実行」を押すと、学習用シミュレータが puts / print / p の出力を表示します(本物のRubyではなく、教材の範囲を再現した軽量な自作エンジンです)。配列・ハッシュ・ブロック(each/map/select)・メソッド・クラス・モジュール・例外なども動きます。本文の例を書き換えて動かしてみましょう(gem・Rails・ファイル入出力など一部の機能は対象外です。文字列を伸ばすときは str << も可能ですが、変数に反映されるのは str += です)。

Ruby — ブラウザ内で実行(学習用シミュレータ)

Rubyの教材サブセットを動かす学習用シミュレータを読み込みます(本物のRubyではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。