[Ruby]Lispっぽく振舞ってみる
On Lispを読んでいてちょっと思いついたネタでも。 RUBY_VERSION >= ‘1.8.7’ でよろしく。
# きもい下準備
instance_exec(self) do |toplevel|
(class << toplevel ; self ; end).class_eval do
define_method :defun do |name, &block|
(class << toplevel ; self ; end).class_eval do
define_method name, &block
end
end
end
end
alias let instance_exec
# 元のCommon Lisp版とRuby版
# (let ((counter 0))
# (defun new-id () (incf counter))
# (defun reset-id () (setq counter 0)))
let(0) do |counter|
defun :new_id do
counter += 1
end
defun :reset_id do
counter = 0
end
end
# 試運転
5.times do
p new_id # => 1, 2, 3, 4, 5
end
reset_id
3.times do
p new_id # => 1, 2, 3
end
発端はselfに対してのinstance_execでletがやれるとオモタこと。
instance_execでトップレベルでのselfをtoplevelに縛り付けてやって、その内側でdefunをModule#definie_methodで定義することで、defunがどっから呼ばれても関数的メソッドをトップレベルに定義したことにできる。
(self « obj ; self ; end)は、きちゃないけどobjの特異クラスを得るためのイディオム。よいこはなるべくマネしちゃダメだぞ。