VIP de Programming

   

気になった発言とか簡易まとめ
ある程度まとまったらwikiにうpしよう!
レス集

[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の特異クラスを得るためのイディオム。よいこはなるべくマネしちゃダメだぞ。

Permalink
Comments (View)
blog comments powered by Disqus