How do I intercept creation of fundatmental types, eg. []

Hi,

I’m new to ruby and I love the introspection and metaprogramming
capabilities. However, I’m having a problem. I want to count the number
of arrays created. I can only intercept and redefine explicit calls to
Array.new

For example, I can catch this:

b = Array.new

but I cannot catch this:

x = [3,4,5]

It seems like I should be able to do it with the awesome power of ruby
:), but I can’t figure out how.

Here is a simple program I am using to try to intercept the creation of
Array (I’ve tried catching “[]”, initialize, new and clone - I also
tried overriding Object.new, but couldn’t get that to work either, but
that code is not included). You’ll notice little newbie commented
questions sprinkled in the code.

The count variable should be 4 because I make 4 arrays. How do I get
that?

Thanks in advance!

#! /usr/bin/env ruby

class Array

@@count = 0

How do I alias Array.new?

alias orig_new method(‘Array.new’)

this doesn’t work either

orig_new = method(‘Array.new’)

def Array.new(*args,&block)
print “In Array.new”
print " with #{args.inspect}" if args
print " and #{block.inspect}" if block
print “\n”
print “\tself.class is #{self.class}\n”
@@count += 1
puts “\tcount is now #{@@count}”
#orig_new
# Is this right?
super
end

this alias does not work

how do refer to this method “[]”?

alias orig_ob_cb method(’[]’)

def [](*args, &block)

puts “In [] … We never seem to get here.”

# this is probably the method for elem = array[]

# a right hand side assignment

orig_ob_cb(*args, &block)

end

alias orig_clone clone
def clone
puts “In clone … Nope we’re not cloning.”
orig_clone
end

alias orig_initialize initialize
def initialize(*args, &block)
puts “An Array was just initialized!”
orig_initialize(*args, &block)
end

def count
@@count
end
end

x = [3,4,5]
puts “x.class is #{x.class}”

notice we have the count attribute, but we never called new

puts “count is #{x.count}”
puts “x is #{x.inspect}”

puts “”
a = Array.new 2, :a
puts “a.class is #{a.class}”
puts “count is #{a.count}”
a << 7
puts “a is #{a.inspect}”

puts “”
b = Array.new 3,3
puts “b.class is #{b.class}”
puts “count is #{b.count}”
b[0] = 7
puts “b is #{b.inspect}”
puts “b[0] is #{b[0]}”

puts “”
c = []
puts “c.class is #{c.class}”
puts “count is #{c.count}”
puts “c is #{c.inspect}”

How i use pointer in ruby?

2007/6/21, Durant S. [email protected]:

On Fri, 22 Jun 2007 05:28:24 +0900, “Durant S.” [email protected]
wrote:

For example, I can catch this:

b = Array.new

but I cannot catch this:

x = [3,4,5]

It seems like I should be able to do it with the awesome power of ruby
:), but I can’t figure out how.

It isn’t possible without modifying the interpreter; in the latter case,
the array is created directly by the interpreter, rather than via a
method call.

-mental

MenTaLguY wrote:

:), but I can’t figure out how.

It isn’t possible without modifying the interpreter; in the latter case,
the array is created directly by the interpreter, rather than via a method call.

And there are other non-method sources of arrays:

def mkary
return 1,2,3
end

GC.start
p ObjectSpace.each_object(Array){}

a = mkary
p ObjectSpace.each_object(Array){}
b = mkary
p ObjectSpace.each_object(Array){}

def mkary2(*args)
args
end

c = mkary2 4,5,6
p ObjectSpace.each_object(Array){}
d = mkary2 7,8,9
p ObjectSpace.each_object(Array){}

GC.start
p ObjectSpace.each_object(Array){}

MenTaLguY wrote:

On Fri, 22 Jun 2007 05:28:24 +0900, “Durant S.” [email protected]
wrote:

For example, I can catch this:

b = Array.new

but I cannot catch this:

x = [3,4,5]

It seems like I should be able to do it with the awesome power of ruby
:), but I can’t figure out how.

It isn’t possible without modifying the interpreter; in the latter case,
the array is created directly by the interpreter, rather than via a
method call.

-mental

Ah, that’s too bad. I was encouraged by seeing the count method show up
in the “x = [3,4,5]” example

Thanks, all.

ps - I figured out how to save and call Array.new below. Fortunately,
though I’m not sure why, this doesn’t cause infinite recursion.

class Array

@@count = 0

orig_new = %s{Array.new}

def Array.new(*args,&block)
print “In Array.new”
print " with #{args.inspect}" if args
print " and #{block.inspect}" if block
print “\n”
print “\tself.class is #{self.class}\n”
@@count += 1
puts “\tcount is now #{@@count}”
#super
orig_new(*args,&block)
end

end

Durant S. wrote:

ps - I figured out how to save and call Array.new below. Fortunately,
though I’m not sure why, this doesn’t cause infinite recursion.

class Array

@@count = 0

orig_new = %s{Array.new}

def Array.new(*args,&block)
print “In Array.new”
print " with #{args.inspect}" if args
print " and #{block.inspect}" if block
print “\n”
print “\tself.class is #{self.class}\n”
@@count += 1
puts “\tcount is now #{@@count}”
#super
orig_new(*args,&block)
end

end

Sorry, that does not work … I was inheriting an orig_new in “class
Class” which is not shown here.

This is what I had:

class Class
alias_method :orig_new, :new
def new(*args,&block)
result = orig_new(*args,&block)
print “In Class.new”
print " with #{args.inspect}" if args
print " and #{block.inspect}" if block
print “\n”
print “\tresult.class is #{result.class}\n”
result
end
end

class Array

@@count = 0

orig_new = %s{Array.new}

def Array.new(*args,&block)
print “In Array.new”
print " with #{args.inspect}" if args
print " and #{block.inspect}" if block
print “\n”
print “\tself.class is #{self.class}\n”
@@count += 1
puts “\tcount is now #{@@count}”
#super
orig_new(*args,&block)
end

end

and I thought it was working…