Is there any way to redefine the `new' method?

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!

On Dec 13, 2007 9:35 AM, pluskid [email protected] wrote:

@@symbols[name]

end
end

First of all, if you want a list or all symbols try:

Symbol.all_symbols

Next, if you want to define a method on the class object itself (i.e.
a class method) the you should try this:

class Symbol
def Symbol.my_new(name)

end
end

Symbol.my_new(‘foo’)

Now, lastly, you should note that new has no implementation on Symbol.
This is deliberate. If you want to create a symbol from a string you
should use the String#to_sym method:

class Symbol
def Symbol.my_new(name)
name.to_sym
end
end

If you want to get into the details of why all this is the way it is,
then please ask. If you want to name my_new to new go ahead but I
wouldn’t count on it being called for symbols being created in literal
style or via String#to_sym.

Brian.

On 12/13/07, pluskid [email protected] wrote:

@@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/

Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

2007/12/13, Rick DeNatale [email protected]:

@@symbols[name] ||= orig_new(name)

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

Good point.

allocate easily since ruby doesn’t use normal method lookup to invoke
it.

In this case you don’t need to override #allocate - #new is perfectly
ok (see below).

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.

It’s not that difficult:

$ ./scheme-symbols.rb
[134314620]
09:32:48 ~/ruby
$ cat ./scheme-symbols.rb
#!/usr/bin/env ruby

module Scheme
Symbol = Struct.new :name

class Symbol
@names = Hash.new do |h, k|
k = k.dup.freeze
h[k] = __new(k)
end

class << self
  alias __new new
  def new(name)
    @names[name]
  end
end

end

end

syms = (1…2).map { Scheme::Symbol.new “foo” }
p syms.map {|o| o.object_id}.uniq

Cheers

robert

Thank you, Robert! I think that’s really what I want! :slight_smile:

On Dec 14, 5:07 pm, “Robert K.” [email protected]

another way:

module Scheme
class Symbol
@names = {}
def self.new name
@names[name.to_sym] ||= super
end
def initialize name
@name = name.to_sym
end
end
end

foo1 = Scheme::Symbol.new(:foo)
foo2 = Scheme::Symbol.new(:foo)
bar1 = Scheme::Symbol.new(:bar)
bar2 = Scheme::Symbol.new(:bar)
puts ((foo1 == foo2) && (bar1 == bar2) && (bar1 != foo1))

2007/12/14, Robert K. [email protected]:

def new(name)
First, Ruby has a core class called Symbol, which is the class of
The new method which is an instance method of the class Class, is
ok (see below).
09:32:48 ~/ruby
end

syms = (1…2).map { Scheme::Symbol.new “foo” }
p syms.map {|o| o.object_id}.uniq

I had forgotton one #freeze:

module Scheme
Symbol = Struct.new :name

class Symbol
@names = Hash.new do |h, k|
k = k.dup.freeze
h[k] = __new(k).freeze
end

class << self
  alias __new new
  def new(name)
    raise ArgumentError, "not a string" unless String === name
    @names[name]
  end
end

end

end

Cheers

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs