[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Alternate initializers or alternate class?

Trans

7/14/2006 11:59:00 PM

Jan Molic recently contacted me about a slighlty modified version of
his OrderedHash class that I distribute in Facets, the Dictionary
class. There are a few variations of this class initself and Jan
originally provided these via a subclass. I, on the other, thought
alternate initializers would be better.

Which is the best approach?

Ex.

class AutoOrderHash < OrderedHash

def new(*args)
super(*args){ |h,k| h[k] = self.class.new }
end

end

vs.

class OrderHash

def self.auto(*args)
new(*args){ |h,k| h[k] = self.class.new }
end

end

Thanks,
T.


10 Answers

Sean O'Halpin

7/15/2006 2:01:00 AM

0

On 7/15/06, transfire@gmail.com <transfire@gmail.com> wrote:
> Jan Molic recently contacted me about a slighlty modified version of
> his OrderedHash class that I distribute in Facets, the Dictionary
> class. There are a few variations of this class initself and Jan
> originally provided these via a subclass. I, on the other, thought
> alternate initializers would be better.
>
> Which is the best approach?
>
> Ex.
>
> class AutoOrderHash < OrderedHash
>
> def new(*args)
> super(*args){ |h,k| h[k] = self.class.new }
> end
>
> end
>
> vs.
>
> class OrderHash
>
> def self.auto(*args)
> new(*args){ |h,k| h[k] = self.class.new }
> end
>
> end
>
> Thanks,
> T.
>
I generally find it easier to remember what general kind of thing I
want (i.e. class) than what specific subtype of thing I want
(alternative initializer). For example, the Date class has a whole
load of alternative initializers which I usually have to look up. I
find it easier to wrap those in specific classes.

Using different classes, you have two pieces of information to correlate:
a) class name
b) signature of initializer

Using alternative initializers, you have three:
a) class name
b) method name of alternative initializer
c) alternative initializer signature

Just my tuppence worth.

Regards,
Sean

Logan Capaldo

7/15/2006 3:10:00 AM

0


On Jul 14, 2006, at 7:58 PM, transfire@gmail.com wrote:

> Jan Molic recently contacted me about a slighlty modified version of
> his OrderedHash class that I distribute in Facets, the Dictionary
> class. There are a few variations of this class initself and Jan
> originally provided these via a subclass. I, on the other, thought
> alternate initializers would be better.
>
> Which is the best approach?
>
> Ex.
>
> class AutoOrderHash < OrderedHash
>
> def new(*args)
> super(*args){ |h,k| h[k] = self.class.new }
> end
>
> end
>
> vs.
>
> class OrderHash
>
> def self.auto(*args)
> new(*args){ |h,k| h[k] = self.class.new }
> end
>
> end
>
> Thanks,
> T.
>
>

The second implemented in terms of the first?

class OrderHash
def self.auto(*args)
AutoOrderHash.new(*args)
end
end

Yes, please have your cake and eat it too. :)


Trans

7/15/2006 3:35:00 AM

0


Logan Capaldo wrote:

> The second implemented in terms of the first?
>
> class OrderHash
> def self.auto(*args)
> AutoOrderHash.new(*args)
> end
> end
>
> Yes, please have your cake and eat it too. :)

Hmmm... I like the "taste" of that ;-)

Thanks,
T.


Daniel Schierbeck

7/15/2006 9:57:00 AM

0

transfire@gmail.com wrote:
> Jan Molic recently contacted me about a slighlty modified version of
> his OrderedHash class that I distribute in Facets, the Dictionary
> class. There are a few variations of this class initself and Jan
> originally provided these via a subclass. I, on the other, thought
> alternate initializers would be better.
>
> Which is the best approach?
>
> Ex.
>
> class AutoOrderHash < OrderedHash
>
> def new(*args)
> super(*args){ |h,k| h[k] = self.class.new }
> end
>
> end
>
> vs.
>
> class OrderHash
>
> def self.auto(*args)
> new(*args){ |h,k| h[k] = self.class.new }
> end
>
> end

I actually favor a third approach; keyword argument options.

OrderHash.new(:auto? => true)

I think Rails has shown us that such option hashes are extremely
powerful and flexible.


Just my $.02
Daniel

Sean O'Halpin

7/15/2006 11:09:00 AM

0

On 7/15/06, transfire@gmail.com <transfire@gmail.com> wrote:
>
> Logan Capaldo wrote:
>
> > The second implemented in terms of the first?
> >
> > class OrderHash
> > def self.auto(*args)
> > AutoOrderHash.new(*args)
> > end
> > end
> >
> > Yes, please have your cake and eat it too. :)
>
> Hmmm... I like the "taste" of that ;-)
>
> Thanks,
> T.
>
+1 - having cake and eating it is a thing devoutly to be wished for ;)

Regards,
Sean

Sean O'Halpin

7/15/2006 11:22:00 AM

0

On 7/15/06, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
> transfire@gmail.com wrote:
> > Jan Molic recently contacted me about a slighlty modified version of
> > his OrderedHash class that I distribute in Facets, the Dictionary
> > class. There are a few variations of this class initself and Jan
> > originally provided these via a subclass. I, on the other, thought
> > alternate initializers would be better.
> >
> > Which is the best approach?
> >
> > Ex.
> >
> > class AutoOrderHash < OrderedHash
> >
> > def new(*args)
> > super(*args){ |h,k| h[k] = self.class.new }
> > end
> >
> > end
> >
> > vs.
> >
> > class OrderHash
> >
> > def self.auto(*args)
> > new(*args){ |h,k| h[k] = self.class.new }
> > end
> >
> > end
>
> I actually favor a third approach; keyword argument options.
>
> OrderHash.new(:auto? => true)
>
> I think Rails has shown us that such option hashes are extremely
> powerful and flexible.
>
>
> Just my $.02
> Daniel
>
I'm a big proponent of keyword arguments (which we implement in the
current version of Ruby using option hashes). However, I'm not sure
it's appropriate for this usage, i.e. selecting which kind of object
is created.

You would have to select which alternative initializer to call in
OrderHash.initialize and extract each different set of arguments
depending on which alternative initializer you're calling. It would
add unnecessary complexity and overhead. It also suffers from the
cognitive load of having to remember three things (class, selector,
which options go with which selector) instead of two (class,
initializer signature). Also, if you add another kind of OrderedHash,
you have to change OrderHash#initialize.

I'm all for keyword ~options~ in initializers which modify some aspect
of the newly created object. I'm just not sure you want to have the
initializer return different classes of object depending on those
options.

BTW, the keyword arguments technique has a long history before Rails
came along ;)

Regards,
Sean

Daniel Schierbeck

7/15/2006 12:09:00 PM

0

Sean O'Halpin wrote:
> On 7/15/06, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
>> transfire@gmail.com wrote:
>> > Jan Molic recently contacted me about a slighlty modified version of
>> > his OrderedHash class that I distribute in Facets, the Dictionary
>> > class. There are a few variations of this class initself and Jan
>> > originally provided these via a subclass. I, on the other, thought
>> > alternate initializers would be better.
>> >
>> > Which is the best approach?
>> >
>> > Ex.
>> >
>> > class AutoOrderHash < OrderedHash
>> >
>> > def new(*args)
>> > super(*args){ |h,k| h[k] = self.class.new }
>> > end
>> >
>> > end
>> >
>> > vs.
>> >
>> > class OrderHash
>> >
>> > def self.auto(*args)
>> > new(*args){ |h,k| h[k] = self.class.new }
>> > end
>> >
>> > end
>>
>> I actually favor a third approach; keyword argument options.
>>
>> OrderHash.new(:auto? => true)
>>
>> I think Rails has shown us that such option hashes are extremely
>> powerful and flexible.
>>
>>
>> Just my $.02
>> Daniel
>>
> I'm a big proponent of keyword arguments (which we implement in the
> current version of Ruby using option hashes). However, I'm not sure
> it's appropriate for this usage, i.e. selecting which kind of object
> is created.
>
> You would have to select which alternative initializer to call in
> OrderHash.initialize and extract each different set of arguments
> depending on which alternative initializer you're calling. It would
> add unnecessary complexity and overhead. It also suffers from the
> cognitive load of having to remember three things (class, selector,
> which options go with which selector) instead of two (class,
> initializer signature). Also, if you add another kind of OrderedHash,
> you have to change OrderHash#initialize.
>
> I'm all for keyword ~options~ in initializers which modify some aspect
> of the newly created object. I'm just not sure you want to have the
> initializer return different classes of object depending on those
> options.
>
> BTW, the keyword arguments technique has a long history before Rails
> came along ;)

Who said anything about multiple classes?

class OrderHash
def initialize(*args)
options = args.shift.to_hash if args.last.respond_to? :to_hash
if options and options.has_key? :auto?
do_something_with{|hsh, key| hsh[key] = self.class.new}
end
end
end

I haven't yet read through the OrderHash/Dictionary code, so it might be
better to put it in ::new


Cheers,
Daniel

Sean O'Halpin

7/15/2006 5:40:00 PM

0

On 7/15/06, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
> Sean O'Halpin wrote:
> > On 7/15/06, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
> >> transfire@gmail.com wrote:
> >> > Jan Molic recently contacted me about a slighlty modified version of
> >> > his OrderedHash class that I distribute in Facets, the Dictionary
> >> > class. There are a few variations of this class initself and Jan
> >> > originally provided these via a subclass. I, on the other, thought
> >> > alternate initializers would be better.
> >> >
> >> > Which is the best approach?
> >> >
> >> > Ex.
> >> >
> >> > class AutoOrderHash < OrderedHash
> >> >
> >> > def new(*args)
> >> > super(*args){ |h,k| h[k] = self.class.new }
> >> > end
> >> >
> >> > end
> >> >
> >> > vs.
> >> >
> >> > class OrderHash
> >> >
> >> > def self.auto(*args)
> >> > new(*args){ |h,k| h[k] = self.class.new }
> >> > end
> >> >
> >> > end
> >>
> >> I actually favor a third approach; keyword argument options.
> >>
> >> OrderHash.new(:auto? => true)
> >>
> >> I think Rails has shown us that such option hashes are extremely
> >> powerful and flexible.
> >>
> >>
> >> Just my $.02
> >> Daniel
> >>
> > I'm a big proponent of keyword arguments (which we implement in the
> > current version of Ruby using option hashes). However, I'm not sure
> > it's appropriate for this usage, i.e. selecting which kind of object
> > is created.
> >
> > You would have to select which alternative initializer to call in
> > OrderHash.initialize and extract each different set of arguments
> > depending on which alternative initializer you're calling. It would
> > add unnecessary complexity and overhead. It also suffers from the
> > cognitive load of having to remember three things (class, selector,
> > which options go with which selector) instead of two (class,
> > initializer signature). Also, if you add another kind of OrderedHash,
> > you have to change OrderHash#initialize.
> >
> > I'm all for keyword ~options~ in initializers which modify some aspect
> > of the newly created object. I'm just not sure you want to have the
> > initializer return different classes of object depending on those
> > options.
> >
> > BTW, the keyword arguments technique has a long history before Rails
> > came along ;)
>
> Who said anything about multiple classes?

Fair enough - I was thinking about the original implementation and
Logan's creative solution.

>
> class OrderHash
> def initialize(*args)
> options = args.shift.to_hash if args.last.respond_to? :to_hash

Don't you think this is rather fragile? What if you want to initialize
with an object that responds to :to_hash but isn't a set of options?
Also, this will fail if no args are passed (minor point).

> if options and options.has_key? :auto?
> do_something_with{|hsh, key| hsh[key] = self.class.new}
> end

Plus similar tests for every other alternative. This doesn't seem to
me to be good design for the reason I gave earlier - if you add new
specialised kinds of hash, you'll have to change (or completely
replace) this initializer. Don't you think it would be a cleaner
design to simply create a new subclass? Isn't this what inheritance is
for? Even reopening the OrderedHash class to add a new alternative
initializer is cleaner.

> end
> end
>

A third point is that having an interface like this means you can't
use OrderedHash and AutoOrderedHash as simple drop-in replacements for
Hash. The same goes for the alternative initializer approach.

Cheers,
Sean

Trans

7/16/2006 12:57:00 PM

0


Sean O'Halpin wrote:

> +1 - having cake and eating it is a thing devoutly to be wished for ;)

Well, it seemed all well and good but now I find myself having to
create Auto versions of every other subclass of Hash. I have a few, so
that start's to get ugly. hmm....

T.


Sean O'Halpin

7/17/2006 3:20:00 AM

0

On 7/16/06, transfire@gmail.com <transfire@gmail.com> wrote:
>
> Sean O'Halpin wrote:
>
> > +1 - having cake and eating it is a thing devoutly to be wished for ;)
>
> Well, it seemed all well and good but now I find myself having to
> create Auto versions of every other subclass of Hash. I have a few, so
> that start's to get ugly. hmm....
>
> T.
>
You don't have to write the code yourself! :)

def make_auto(*classes)
classes.each do |klass|
new_class = Class.new klass do
def initialize(*args)
super(*args){ |h,k| h[k] = self.class.new }
end
end
Object.const_set("Auto#{klass}", new_class)
end
end

class OrderedHash < Hash
# do something here
end

make_auto Hash, OrderedHash

ah = AutoHash.new
aoh = AutoOrderedHash.new

p ah[:a]
p aoh[:b]
__END__
{}
{}

Regards,
Sean