Hi! I'm writing a toy interpreter for scheme in Ruby. I created a
class to represent scheme Symbol.
And as the scheme Symbol, I want only one instance for symbols with
the same name. I try to
do it like this:
class Symbol
alias orig_new new
def new(name)
@@symbols[name] ||= orig_new(name)
@@symbols[name]
end
end
But I failed. It says `new' is undefined. Is there any way to do the
tricky? Thanks!
Well.
First, Ruby has a core class called Symbol, which is the class of
those funny :abc thingies. You probably don't want to mess with it,
and it might just already do what your are looking for. Note that you
can't do Symbol.new symbol instances are created either as literals,
or with conversion methods like "abc".to_sym
Second, Ruby probably does instance instantiation and initialization a
bit differently than whatever language you might be familiar with.
The new method which is an instance method of the class Class, is
normally never overridden, and it really isn't intended to be. It
effectively calls another method initialize to allocate the space for
the object, and then calls initialize on the result passing the
arguments of new.
The way Class#new does this is a bit magical. You can't override
allocate easily since ruby doesn't use normal method lookup to invoke
it. This works for ruby since, unlike many other OO languages, the
space needed for an object doesn't depend on things how many instance
variables it has, since these are acquired dynamically and found via a
hash.
If Symbol doesn't do the job for you, you might look at things like
Ara's multiton code
http://raa.ruby-lang.org/project/multiton/