[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

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

Chiyuan Zhang

12/13/2007 2:34:00 PM

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!
6 Answers

Brian Mitchell

12/13/2007 2:52:00 PM

0

On Dec 13, 2007 9:35 AM, pluskid <pluskid@gmail.com> wrote:
> 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

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.

Rick DeNatale

12/13/2007 5:01:00 PM

0

On 12/13/07, pluskid <pluskid@gmail.com> wrote:
> 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...
--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Robert Klemme

12/14/2007 8:35:00 AM

0

2007/12/13, Rick DeNatale <rick.denatale@gmail.com>:
> On 12/13/07, pluskid <pluskid@gmail.com> wrote:
> > 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

Good point.

> 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.

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

--
use.inject do |as, often| as.you_can - without end

Robert Klemme

12/14/2007 9:08:00 AM

0

2007/12/14, Robert Klemme <shortcutter@googlemail.com>:
> 2007/12/13, Rick DeNatale <rick.denatale@gmail.com>:
> > On 12/13/07, pluskid <pluskid@gmail.com> wrote:
> > > 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
>
> Good point.
>
> > 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.
>
> 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

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
--
use.inject do |as, often| as.you_can - without end

Chiyuan Zhang

12/14/2007 9:37:00 AM

0

Thank you, Robert! I think that's really what I want! :)

On Dec 14, 5:07 pm, "Robert Klemme" <shortcut...@googlemail.com>
wrote:
> 2007/12/14, Robert Klemme <shortcut...@googlemail.com>:
>
>
>
> > 2007/12/13, Rick DeNatale <rick.denat...@gmail.com>:
> > > On 12/13/07, pluskid <plus...@gmail.com> wrote:
> > > > 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
>
> > Good point.
>
> > > 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.
>
> > 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
>
> 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
> --
> use.inject do |as, often| as.you_can - without end

Christophe Mckeon

12/14/2007 2:24:00 PM

0

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))
--
Posted via http://www.ruby-....