Alternate initializers or alternate class?

Discussion in 'Ruby' started by transfire@gmail.com, Jul 15, 2006.

  1. Guest

    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.
     
    , Jul 15, 2006
    #1
    1. Advertising

  2. On 7/15/06, <> 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
     
    Sean O'Halpin, Jul 15, 2006
    #2
    1. Advertising

  3. On Jul 14, 2006, at 7:58 PM, 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. :)
     
    Logan Capaldo, Jul 15, 2006
    #3
  4. Guest

    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.
     
    , Jul 15, 2006
    #4
  5. 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
     
    Daniel Schierbeck, Jul 15, 2006
    #5
  6. On 7/15/06, <> 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, Jul 15, 2006
    #6
  7. On 7/15/06, Daniel Schierbeck <> wrote:
    > 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
     
    Sean O'Halpin, Jul 15, 2006
    #7
  8. Sean O'Halpin wrote:
    > On 7/15/06, Daniel Schierbeck <> wrote:
    >> 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
     
    Daniel Schierbeck, Jul 15, 2006
    #8
  9. On 7/15/06, Daniel Schierbeck <> wrote:
    > Sean O'Halpin wrote:
    > > On 7/15/06, Daniel Schierbeck <> wrote:
    > >> 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
     
    Sean O'Halpin, Jul 15, 2006
    #9
  10. Guest

    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.
     
    , Jul 16, 2006
    #10
  11. On 7/16/06, <> 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
     
    Sean O'Halpin, Jul 17, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Glen Able

    Class variable initializers

    Glen Able, Jan 29, 2004, in forum: Java
    Replies:
    0
    Views:
    335
    Glen Able
    Jan 29, 2004
  2. j l
    Replies:
    5
    Views:
    395
    A. Bolmarcich
    Feb 23, 2004
  3. James Robert Leek

    JNI Invocation: static UN-initializers?

    James Robert Leek, Aug 31, 2004, in forum: Java
    Replies:
    2
    Views:
    492
    James Robert Leek
    Aug 31, 2004
  4. Chris
    Replies:
    2
    Views:
    706
    Chris
    Mar 4, 2007
  5. Bhrgunatha Deva

    Class (not instance) initializers

    Bhrgunatha Deva, Mar 21, 2006, in forum: Ruby
    Replies:
    5
    Views:
    105
Loading...

Share This Page