Re: Rubyのdefの後に何を書けるか調べる実験

sinsoku.hatenablog.com

最後のHashが印象的。以下引用。

# no error
def ({}).foo
  puts "foo"
end

# 別インスタンスなのでメソッドは呼べない
{}.foo
#=> (NoMethodError)

引用終了。

さて、別インスタンスなので呼べないというが、まあ呼びたいじゃん?オブジェクト作ってるんだから ObjectSpace から引っ張ってくればええやん?

def show_hash(h)
  if h
    p h
    p (h.methods - ({}.methods))
  else
    puts "nil"
  end
end

def search_object_with_method(name:)
  ObjectSpace.each_object.find { |e| e.methods.include?(name) }
end

def ({}).foo
  $a = self
end

h = search_object_with_method(name: :foo)
show_hash(h)

試してみまして。

$ ruby foo.rb
{}
[:foo]

ok

ついでだから初期化されたやつも試してみまして。

def show_hash(h)
  if h
    p h
    p (h.methods - ({}.methods))
  else
    puts "nil"
  end
end

def search_object_with_method(name:)
  ObjectSpace.each_object.find { |e| e.methods.include?(name) }
end

def ({}).foo
  $a = self
end

h = search_object_with_method(name: :foo)
show_hash(h)

# ここから追記

puts '-' * 20

def ({a: 1}).bar
end

h = search_object_with_method(name: :bar)
show_hash(h)

まあ、出るっしょ。

$ ruby foo.rb
{}
[:foo]
--------------------
nil

nil !?!?!?!?

え、初期化するかどうかで振る舞い違うの!?ヤバくない?って思ったらGCのせいでした。どこにもバインドしてないからしょうがないね。

GC.disable # これを追加

def show_hash(h)
  if h
    p h
    p (h.methods - ({}.methods))
  else
    puts "nil"
  end
end

def search_object_with_method(name:)
  ObjectSpace.each_object.find { |e| e.methods.include?(name) }
end

def ({}).foo
  $a = self
end

h = search_object_with_method(name: :foo)
show_hash(h)

puts '-' * 20

def ({a: 1}).bar
end

h = search_object_with_method(name: :bar)
show_hash(h)
$ ruby foo.rb
{}
[:foo]
--------------------
{:a=>1}
[:bar]

hanachin さんが調べてくれてたけど NODE_HASH が載ってないですね。わざとなのかしら。