[suby-ruby] Your all time desired fundemental Ruby mod

I'm more a fan of make it right, make it work, make it fast.

It's definitely wrong if it doesn't work.

You would have to do it via class instance vars. The problem with these IMHO
is still the intialization issue, as with modules (see ruby-talk:121611,
http://urltron.com/nd\) Matz, do you think we can get something in the way of
remedying that? For me it's one of the biggest sores in my code.

···

On Monday 17 January 2005 02:51 am, Martin DeMello wrote:

David A. Black <dblack@wobblini.net> wrote:
> You're right -- I meant to clarify that I'm talking about 2.0 class
> vars, which as I understand it will be truly per-class and will differ
> from instance variables of Class objects principally in that they will
> be in scope in instance methods. I would rather not have a separate
> construct that overlaps so much with instance variables.

I can think of at least one good us for the current @@ variables -
subclassable GUI components that inherit hierarchy-shared look-and-feel
properties from the parent class. What would be the elegant way to do
this if @@ variables go per-class?

Hi --

···

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:

I generally agree with you. I wonder if @@vars could just become somesort of
across the board initializer/accessor for instance vars (ie. @vars).

class C
   @@a = 10
   def a; @a; end
end
C.new.a #=> 10

Here you've got one object assigning to another object's instance
variables, which is not good.

David

--
David A. Black
dblack@wobblini.net

Martin DeMello ha scritto:

···

David A. Black <dblack@wobblini.net> wrote:

You're right -- I meant to clarify that I'm talking about 2.0 class
vars, which as I understand it will be truly per-class and will differ
from instance variables of Class objects principally in that they will
be in scope in instance methods. I would rather not have a separate
construct that overlaps so much with instance variables.

I can think of at least one good us for the current @@ variables -
subclassable GUI components that inherit hierarchy-shared look-and-feel
properties from the parent class. What would be the elegant way to do
this if @@ variables go per-class?

constants ?

Hi --

> > You're right -- I meant to clarify that I'm talking about 2.0 class
> > vars, which as I understand it will be truly per-class and will differ
> > from instance variables of Class objects principally in that they will
> > be in scope in instance methods. I would rather not have a separate
> > construct that overlaps so much with instance variables.
>
> I can think of at least one good us for the current @@ variables -
> subclassable GUI components that inherit hierarchy-shared look-and-feel
> properties from the parent class. What would be the elegant way to do
> this if @@ variables go per-class?

You would have to do it via class instance vars.

They're per-class too :slight_smile: You'd need accessor methods, I think.

The problem with these IMHO
is still the intialization issue, as with modules (see ruby-talk:121611,
http://urltron.com/nd\) Matz, do you think we can get something in the way of
remedying that? For me it's one of the biggest sores in my code.

I'm not sure I get what the problem is here. In your examples you're
overriding #initialize, and calling super to invoke the old one.
That's pretty standard procedure -- it's what super is basically for,
and it seems like the simplest design. (I'm not sure what's supposed
to happen in the future if instance vars become private to their
module.)

David

···

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:

On Monday 17 January 2005 02:51 am, Martin DeMello wrote:
> David A. Black <dblack@wobblini.net> wrote:

--
David A. Black
dblack@wobblini.net

Except that class vars already do so in a sense in that they are accessable
from both the class level and the instance level. But even so, that's not
really what I meant. I'm actually with you on deprecating class vars, and was
instead considering a completely alternate use for @@ notation to mean
"default value of instance vars". This would address the issue in my other
post about initialization of module's instance vars too, i.e.

  module M
    @@a = 10
    def a; @a; end
  end

  class C
    include M
  end

  C.new.a #=> 10

But maybe you already understood this and still find it not good?

T.

···

On Monday 17 January 2005 08:20 am, David A. Black wrote:

Hi --

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:
> I generally agree with you. I wonder if @@vars could just become somesort
> of across the board initializer/accessor for instance vars (ie. @vars).
>
> class C
> @@a = 10
> def a; @a; end
> end
> C.new.a #=> 10

Here you've got one object assigning to another object's instance
variables, which is not good.

Constants aren't modifiable at run time (well, you aren't supposed to
modify them). I was thinking of a scheme whereby you could simply modify
the current theme and have all subclassed widgets pick up on that. A
shared access method to an entirely separate Theme object might do it,
but I still think @@variables are the elegant solution in this case.

martin

···

gabriele renzi <rff_rff@remove-yahoo.it> wrote:

Martin DeMello ha scritto:
> I can think of at least one good us for the current @@ variables -
> subclassable GUI components that inherit hierarchy-shared look-and-feel
> properties from the parent class. What would be the elegant way to do
> this if @@ variables go per-class?

constants?

How?

class Button
  @@background = BLUE
  
  def repaint
    @background = @@background
    ...
  end
end

class ImageButton < Button
end

Now if @@background were changed to Button.@background, how would
repaint work in ImageButton?

martin

···

"trans. (T. Onoma)" <transami@runbox.com> wrote:

On Monday 17 January 2005 02:51 am, Martin DeMello wrote:
>
> I can think of at least one good us for the current @@ variables -
> subclassable GUI components that inherit hierarchy-shared look-and-feel
> properties from the parent class. What would be the elegant way to do
> this if @@ variables go per-class?

You would have to do it via class instance vars. The problem with these IMHO
is still the intialization issue, as with modules (see ruby-talk:121611,
http://urltron.com/nd\) Matz, do you think we can get something in the way of
remedying that? For me it's one of the biggest sores in my code.

Hi --

> Hi --
>
> > I generally agree with you. I wonder if @@vars could just become somesort
> > of across the board initializer/accessor for instance vars (ie. @vars).
> >
> > class C
> > @@a = 10
> > def a; @a; end
> > end
> > C.new.a #=> 10
>
> Here you've got one object assigning to another object's instance
> variables, which is not good.

Except that class vars already do so in a sense in that they are accessable
from both the class level and the instance level.

Class vars themselves have that scope, but they don't set instance
vars.

But even so, that's not
really what I meant. I'm actually with you on deprecating class vars, and was
instead considering a completely alternate use for @@ notation to mean
"default value of instance vars". This would address the issue in my other
post about initialization of module's instance vars too, i.e.

module M
   @@a = 10
   def a; @a; end
end

class C
   include M
end

C.new.a #=> 10

But maybe you already understood this and still find it not good?

Yes :slight_smile: You've got one object (M) setting another object's instance
variables (those of C.new), without the owner-object's consent. I
know that there are already things like instance_variable_set and so
on that can do this... but I personally take a pretty hard line on
instance variables being strictly the business of the instance whose
variables they are. I don't think there should be a proliferation of
mechanisms for crossing that boundary.

David

···

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:

On Monday 17 January 2005 08:20 am, David A. Black wrote:
> On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:

--
David A. Black
dblack@wobblini.net

Hi --

> > > You're right -- I meant to clarify that I'm talking about 2.0 class
> > > vars, which as I understand it will be truly per-class and will
> > > differ from instance variables of Class objects principally in that
> > > they will be in scope in instance methods. I would rather not have a
> > > separate construct that overlaps so much with instance variables.
> >
> > I can think of at least one good us for the current @@ variables -
> > subclassable GUI components that inherit hierarchy-shared look-and-feel
> > properties from the parent class. What would be the elegant way to do
> > this if @@ variables go per-class?
>
> You would have to do it via class instance vars.

They're per-class too :slight_smile: You'd need accessor methods, I think.

Yes, of course: "via class instance thru via accessors" is waht I should have
said.

> The problem with these IMHO
> is still the intialization issue, as with modules (see ruby-talk:121611,
> http://urltron.com/nd\) Matz, do you think we can get something in the way
> of remedying that? For me it's one of the biggest sores in my code.

I'm not sure I get what the problem is here. In your examples you're
overriding #initialize, and calling super to invoke the old one.
That's pretty standard procedure -- it's what super is basically for,
and it seems like the simplest design. (I'm not sure what's supposed
to happen in the future if instance vars become private to their
module.)

Yes, true. But good SOC/ecapsulation meants that I should be able to modify a
class with a module without having to adjust pre-existing parts of the class.
For instance lets say I have class:

  class C
    def initialize
      @y = 11
    end
  end

I want to expand the functionality of this class with a module I have:

  module M
    def x ; @x ; end
  end

But @x needs to default to an array. So what do I do? Presently I have two
choices. Either change M to:

  module M
    def x ; @x ||= ; end
  end

or use super as you suggest. But I don;t want to just recopy C for what if it
changed internally later? So,

  module M
    def initialize
      @x =
    end
    def x ; @x ; end
  end

  class C
    alias_method :init, :initialize
    def initialize(*args, &blk)
      super
      init
    end
  end

None of this is need though if we just had some way to "initialize_always".

Does that explain better?
T.

···

On Monday 17 January 2005 08:33 am, David A. Black wrote:

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:
> On Monday 17 January 2005 02:51 am, Martin DeMello wrote:
> > David A. Black <dblack@wobblini.net> wrote:

Martin DeMello ha scritto:

···

gabriele renzi <rff_rff@remove-yahoo.it> wrote:

Martin DeMello ha scritto:

I can think of at least one good us for the current @@ variables -
subclassable GUI components that inherit hierarchy-shared look-and-feel
properties from the parent class. What would be the elegant way to do
this if @@ variables go per-class?

constants?

Constants aren't modifiable at run time (well, you aren't supposed to
modify them).

well, my problem is that thinking of somthing shared beetween a whole hierarky makes me think of something not modifiable, or at least not supposed to change much. Maybe I just can't think of an example, and theme sqitching is one of those "not supposed to happen often" things.
Obviously, imho.

BTW I personally like your style: Button.@background :wink:

Try:

  class Button
    class < self
      def background
        @background ||= BLUE
      end
    end

    def repaint
      @background = self.class.background
      ...
    end
  end

  class ImageButton < Button
  end

That's the idea. Work for you?

T.

···

On Tuesday 18 January 2005 12:21 am, Martin DeMello wrote:

"trans. (T. Onoma)" <transami@runbox.com> wrote:
> On Monday 17 January 2005 02:51 am, Martin DeMello wrote:
> > I can think of at least one good us for the current @@ variables -
> > subclassable GUI components that inherit hierarchy-shared look-and-feel
> > properties from the parent class. What would be the elegant way to do
> > this if @@ variables go per-class?
>
> You would have to do it via class instance vars. The problem with these
> IMHO is still the intialization issue, as with modules (see
> ruby-talk:121611, http://urltron.com/nd\) Matz, do you think we can get
> something in the way of remedying that? For me it's one of the biggest
> sores in my code.

How?

class Button
  @@background = BLUE

  def repaint
    @background = @@background
    ...
  end
end

class ImageButton < Button
end

Now if @@background were changed to Button.@background, how would
repaint work in ImageButton?

Martin DeMello wrote:

Martin DeMello ha scritto:

I can think of at least one good us for the current @@ variables -
subclassable GUI components that inherit hierarchy-shared look-and-feel
properties from the parent class. What would be the elegant way to do
this if @@ variables go per-class?

constants?

Constants aren't modifiable at run time (well, you aren't supposed to
modify them). I was thinking of a scheme whereby you could simply modify
the current theme and have all subclassed widgets pick up on that. A
shared access method to an entirely separate Theme object might do it,
but I still think @@variables are the elegant solution in this case.

One limitation of @@var for this purpose is that a subclass cannot decide that it wants to override the base class's binding--if you assign to @@var in a subclass, you affect every class that inherits from the base.

Another problem with @@var is that the order of initialization affects how many bindings exist:

=== two-bindings.rb ===
class A
end

class B < A
   @@v = 1
end

class A
   @@v = 2
end

class A
   puts @@v # ==> 2
end

class B
   puts @@v # ==> 1
end

···

gabriele renzi <rff_rff@remove-yahoo.it> wrote:

======================

=== one-binding.rb ===
class A
   @@v = 2
end

class B < A
   @@v = 1
end

class A
   puts @@v # ==> 1
end

class B
   puts @@v # ==> 1
end

So class vars have these problems, constants are not mutable, and class instance vars do not inherit. That's where superhash (on RAA) might help. It can be used to set up hashes that inherit along the class hierarchy (or other structure, such as a tree or dag). Internally, it uses class instance variables. A really trivial example:

=== superhash-example.rb ===
require 'superhash'

class A
   class_superhash :options

   options[:foo] = "A foo"
   options[:bar] = "A bar"

   def options; self.class.options; end
end

class B < A
   options[:foo] = "B foo"
end

p A.options
p B.options.to_hash
p B.new.options.to_hash

__END__

output:

{:foo=>"A foo", :bar=>"A bar"}
{:foo=>"B foo", :bar=>"A bar"}

So B can inherit and optionally override attributes from A, and the granularity is per key in the hash.

I understand were your coming form, but in this case I don't think that's
what's happening. The class defines the nature of its instances. So its not
like some other unrelated object getting involved. I just presenting a way
fro a class to define the instance vars of its instances. In a way it is kind
of like Hash.new blocks.

T.

···

On Monday 17 January 2005 09:21 am, David A. Black wrote:

Yes :slight_smile: You've got one object (M) setting another object's instance
variables (those of C.new), without the owner-object's consent. I
know that there are already things like instance_variable_set and so
on that can do this... but I personally take a pretty hard line on
instance variables being strictly the business of the instance whose
variables they are. I don't think there should be a proliferation of
mechanisms for crossing that boundary.

Hi --

I wrote

>
> I'm not sure I get what the problem is here. In your examples you're
> overriding #initialize, and calling super to invoke the old one.
> That's pretty standard procedure -- it's what super is basically for,
> and it seems like the simplest design. (I'm not sure what's supposed
> to happen in the future if instance vars become private to their
> module.)

Yes, true. But good SOC/ecapsulation meants that I should be able to modify a
class with a module without having to adjust pre-existing parts of the class.
For instance lets say I have class:

class C
   def initialize
     @y = 11
   end
end

I want to expand the functionality of this class with a module I have:

module M
   def x ; @x ; end
end

But @x needs to default to an array. So what do I do? Presently I have two
choices. Either change M to:

module M
   def x ; @x ||= ; end
end

or use super as you suggest. But I don;t want to just recopy C for what if it
changed internally later? So,

module M
   def initialize
     @x =
   end
   def x ; @x ; end
end

class C
   alias_method :init, :initialize
   def initialize(*args, &blk)
     super
     init
   end
end

None of this is need though if we just had some way to "initialize_always".

I think once you've decided to include a module, you've unseparated
your concerns. Modules you include are gray boxes rather than black
boxes; the class that includes them is adding things to its method
lookup chain, with the same implications that writing a method in the
class itself has. It's true that you're not responsible for
implementing the module's methods (that's where the gray comes from),
but it's still part of the design of your class, and as maintainer of
the class that's part of what you have to deal with.

I think that's a strength of Ruby's design, though. Think of it as a
resource you can draw on, rather than a snag :slight_smile:

David

···

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:

--
David A. Black
dblack@wobblini.net

Hi,

···

In message "Re: Fwd: [suby-ruby] Your all time desired fundemental Ruby mod" on Mon, 17 Jan 2005 23:22:30 +0900, "trans. (T. Onoma)" <transami@runbox.com> writes:

I want to expand the functionality of this class with a module I have:

module M
   def x ; @x ; end
end

But @x needs to default to an array. So what do I do? Presently I have two
choices. Either change M to:

module M
   def x ; @x ||= ; end
end

or use super as you suggest. But I don;t want to just recopy C for what if it
changed internally later?

Initializing module instance variables are one of the things I want to
fix. But I'm not sure what is the best way to fix. Maybe AOP-like
hooks is the way to go. I'm waiting the conviction to come.

              matz.

BTW I personally like your style: Button.@background :wink:

:slight_smile:

Try:

  class Button
    class < self
      def background
        @background ||= BLUE
      end
    end

    def repaint
      @background = self.class.background
      ...
    end
  end

  class ImageButton < Button
  end

That's the idea. Work for you?

No, becaus the idea is that ImageButton will *not* inherit @background
from Button, it being a separate object.

martin

···

"trans. (T. Onoma)" <transami@runbox.com> wrote:

Excellent! I'd forgotten about this.

martin

···

Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

So class vars have these problems, constants are not mutable, and class
instance vars do not inherit. That's where superhash (on RAA) might
help. It can be used to set up hashes that inherit along the class
hierarchy (or other structure, such as a tree or dag). Internally, it
uses class instance variables. A really trivial example:

Sorry, that should read:

I'm just presenting a way for a class to define the _default values_ of
instance vars of its instances.

T.

···

On Monday 17 January 2005 09:29 am, trans. (T. Onoma) wrote:

I just presenting a way
fro a class to define the instance vars of its instances.

Hi --

> Yes :slight_smile: You've got one object (M) setting another object's instance
> variables (those of C.new), without the owner-object's consent. I
> know that there are already things like instance_variable_set and so
> on that can do this... but I personally take a pretty hard line on
> instance variables being strictly the business of the instance whose
> variables they are. I don't think there should be a proliferation of
> mechanisms for crossing that boundary.

I understand were your coming form, but in this case I don't think that's
what's happening. The class defines the nature of its instances. So its not
like some other unrelated object getting involved. I just presenting a way
fro a class to define the default values of the instance vars of its instances. In a way it is kind of like Hash.new blocks.

My perspective is that this is already a specific, fully-designed
case: every object has instance variables, and they belong to that
object. So when you say "the class defines the nature of its
instances", you're backing out into an unnecessarily general and
distant view. My answer is: no, apparently it doesn't, in that sense,
as we can see by the way instance variables are designed :slight_smile:

Similarly, it's true that a class and its objects are "related" -- but
that doesn't mean that any feature or even nuance of language design
where they behave separately has to be or should be removed. There's
ample room inside class definitions to do all the things you're
talking about, going through conventional, "polite" channels:

   class C
     def x
       @x ||= 10
     end
   end

etc.

David

···

On Mon, 17 Jan 2005, trans. (T. Onoma) wrote:

On Monday 17 January 2005 09:21 am, David A. Black wrote:

--
David A. Black
dblack@wobblini.net