URubyリリース!

Merry Christmatz!!*1

今年もクリスマスRubyの季節がやって来ました。今回のRubyは「U」です。

・・・

RubySmalltalkの関係についてはいろんな受け取り方があるようですが、利用感がなんとなく似てるのは事実でしょう。しかし我々Rubyistにとっては残念なことに、フリーダムさという点でRubySmalltalkに一歩劣ると言わざるを得ません。

例えばSmalltalkにはSmalltalk環境自身を表す"Smalltalk"というのグローバル変数があります。これは変数ですから値を再代入できます。Squeakを持っている人は"MVC Project"を開き*2ワークスペースで次の様に入力してください。

ポチッ(Command+d)とな。




はい、実行するとフリーズしてなにも反応が帰って来なくなりますので、Squeakを強制終了してください。

このようにSmalltalkは自らの意志でいっさいを虚無に帰して消え去ることさえ許しているのです。自由に生きることは言い換えれば自由に死に方を選べるということ。これこそがSmalltalkにおける自由の象徴といえるでしょう。

そんな自由がRubyにも欲しいと思いませんか?

Rubyにも喫茶なんかじゃない、本当の自由を。

・・・

http://github.com/technohippy/uruby

という訳でURubyを作りました。UはUndefです。URubyではクラスにnilを代入することでそのクラスを(擬似的に)なかったことにできます。

class Parent
  def greeting
    puts "hello"
  end
end

class Child < Parent
end

child = Child.new
child.greeting #=> "hello"
Parent = nil
child.greeting #=> undefined method `greeting' for #<Child:0x...> (NoMethodError)

nilが代入されたクラスのメソッドは一切呼べません。nilだからnewできませんし、継承したクラスも定義できません。さらに親クラスのinitializeが呼び出される子クラスもnewできません。

Fixnum = nil
1 + 1 #=> undefined method `+' for 1:Fixnum (NoMethodError)
Array = nil 
a = [1,2,3]
a[0] #=> undefined method `[]' for [1, 2, 3]:Array (NoMethodError)

リテラルはなかった事にはできないけど、とりあえず何にもできなくなります。

Object = nil
puts "hello" #=> undefined method `puts' for #<Object:0x...> (NoMethodError)
Object = nil
class Parent; end #=> Object does not exists. (RuntimeError)

Object = nilするとputsを含むいわゆる関数は全部使えなくなります。もちろんObject由来のメソッドは全部使えません。親クラス指定なしのクラスも定義できません。

あとこれは完全におまけだけど

RubyVM = nil

とするとその場でフリーズします。フリーズというかスリープ。

ということで、2010年のクリスマス、Rubyistは本当の自由を手に入れることができました。
Merry Christmatz!!

*1:メリー・クリスマッツこれは流行る!

*2:去勢されたMorphic Projectではnilを代入しても期待したような(壊滅的な)動作にはなりません

URubyの作り方

ホントは他に作りたいものがあったんだけど、どうしても動かなくて諦めました。間に合わせででっち上げたのでかなり手抜き・・・。

variable.c

static void 
mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
{
    // ..snip..
            if ((VALUE)value == Qundef)
                autoload_delete(klass, id); 
            else if (val == Qnil) {
                autoload_delete(klass, id); 
                rb_funcall(value, rb_intern("undef_class"), 0, 0);
            }    
            else 
                rb_warn("already initialized %s %s", dest, rb_id2name(id));
    // ..snip..    
}

定数にnilが代入されたときにundef_classメソッド呼ぶだけ。最初はst_delete(rb_class_tbl, id, 0);とかやろうとしたけど落ちまくるので・・・。

undef_classの実装はprelude.rbの中。

prelude.rb

class RubyVM
  def self.undef_class
    sleep   
    exit        
  end           
end             

class Object
  def self.undef_class
    eval %Q{
      def self.inherited(subclass)
        raise "#{self.name} does not exists."
      end       
    }   
    
    self.included_modules.each do |mod|
      (mod.singleton_methods - [:raise]).each do |m|
        undef_method m
      end
    end

    (self.instance_methods - (self.superclass.instance_methods rescue [])).each do |m|
      undef_method m
    end

    undef_method :initialize
    define_method :initialize do
      raise "#{self.name} does not exists."
    end  
  end
end

うん。ショボイね。来年はもうちょっと頑張るよ。