Using underscores for "private" instance variables?

I noticed that Rails core is adopting a style of using an underscore
at the start of an ivar name, like @_env. (see the short thread at
http://groups.google.com/group/rubyonrails-core/browse_thread/thread/a45de7e435c6c22a)

I kind of hate leading underscores. They remind me of my C++
days :slight_smile: The reasoning sounds logical enough: for ivars that are
supposed to be "private" the class/module, it helps avoid naming
conflicts with client code that includes/derives from that module or
class that wants to keep "it's own" ivars.

But I haven't seen anyone else need to do this in their modules/
classes, so now I'm wondering - has anyone else needed to do this? It
seems like this would be a common problem for any shared Ruby library,
so now I'm wondering why I *haven't* run into this before.

Jeff

As things get sufficiently, complex, I think that something like this
might be reasonable. Prawn is edging on needing some support for
avoiding name clashes, since it carries a lot of internal state in the
Document class and utilizes many mixins.
I'm not sure if this is the convention we'll use, but it's one possibility.

路路路

On Tue, Jan 12, 2010 at 10:33 AM, Jeff <cohen.jeff@gmail.com> wrote:

But I haven't seen anyone else need to do this in their modules/
classes, so now I'm wondering - has anyone else needed to do this? It
seems like this would be a common problem for any shared Ruby library,
so now I'm wondering why I *haven't* run into this before.

I brought up using underscores a long time ago. :slight_smile:

Regards,

Dan

路路路

On Jan 12, 8:48 am, Gregory Brown <gregory.t.br...@gmail.com> wrote:

On Tue, Jan 12, 2010 at 10:33 AM, Jeff <cohen.j...@gmail.com> wrote:
> But I haven't seen anyone else need to do this in their modules/
> classes, so now I'm wondering - has anyone else needed to do this? It
> seems like this would be a common problem for any shared Ruby library,
> so now I'm wondering why I *haven't* run into this before.

As things get sufficiently, complex, I think that something like this
might be reasonable. Prawn is edging on needing some support for
avoiding name clashes, since it carries a lot of internal state in the
Document class and utilizes many mixins.
I'm not sure if this is the convention we'll use, but it's one possibility.

Gregory, that's interesting. Maybe any Ruby library that reaches
sufficent mass use will run into this problem.

But I think the underscore doesn't really solve the problem, right?

Let's say you use @_file in your module that I include. You probably
use #nodoc# around it so I don't even see it in the rdocs. So then my
class I'm about to do @file, but I think, someone might derive from my
class, so I'd better call it @_file. Collision again.

So I say, let's not use the hard-to-read underscores, and document
ivars in the rdocs like everything else.

Of course, it's not that I like my solution either... :frowning: I'm just
not seeing how adding underscores solves the problem.

Jeff

路路路

On Jan 12, 9:48 am, Gregory Brown <gregory.t.br...@gmail.com> wrote:

On Tue, Jan 12, 2010 at 10:33 AM, Jeff <cohen.j...@gmail.com> wrote:
> But I haven't seen anyone else need to do this in their modules/
> classes, so now I'm wondering - has anyone else needed to do this? It
> seems like this would be a common problem for any shared Ruby library,
> so now I'm wondering why I *haven't* run into this before.

As things get sufficiently, complex, I think that something like this
might be reasonable. Prawn is edging on needing some support for
avoiding name clashes, since it carries a lot of internal state in the
Document class and utilizes many mixins.
I'm not sure if this is the convention we'll use, but it's one possibility.

Gregory, that's interesting. Maybe any Ruby library that reaches
sufficent mass use will run into this problem.

But I think the underscore doesn't really solve the problem, right?

Let's say you use @_file in your module that I include. You probably
use #nodoc# around it so I don't even see it in the rdocs. So then my
class I'm about to do @file, but I think, someone might derive from my
class, so I'd better call it @_file. Collision again.

In either case, it's your fault if you don't read upstream source.
But if you're trying to make life easier downstream, it's less likely
to clash with @_file than it is with @file by accident.

But I agree, @_whatever is ugly and I'm not sure I will introduce it
into Prawn. I just understand why the Rails guys did it after having
a bit of direct experience.

So I say, let's not use the hard-to-read underscores, and document
ivars in the rdocs like everything else.

I don't think that internal state benefits from public documentation,
as that just invites one more thing that can get out of date fast, and
invites more danger than it's worth.

I think one real solution is to avoid ivar references in modules
(using method calls), and prefer composition over sub-classing. But
this is edging on the sort of discipline you'd find in functional
languages, which tends to feel a bit too stuffy for some folks.

I'm about to do some major refactoring in Prawn in the near future. I
might play with these thoughts and see where they lead. If I shake
anything loose that's worth sharing, I'll write it up on the RBP blog.

-greg

路路路

On Tue, Jan 12, 2010 at 9:11 PM, Jeff <cohen.jeff@gmail.com> wrote:

On Jan 12, 9:48 am, Gregory Brown <gregory.t.br...@gmail.com> wrote:

I don't think it's about avoiding name clashes but a kind of 'Hungarian
Notation': When looking at a variable name you immediately see it's
intention. No need to browse any rdoc or check when it was first
initialized. I sometimes name variables with an underscore if they are
not intended to be accessed from the outside via attr, attr_reader etc..

martin

路路路

On Wed, 13 Jan 2010 11:11:34 +0900 Jeff <cohen.jeff@gmail.com> wrote:

On Jan 12, 9:48 am, Gregory Brown <gregory.t.br...@gmail.com> wrote:
> On Tue, Jan 12, 2010 at 10:33 AM, Jeff <cohen.j...@gmail.com> wrote:
> > But I haven't seen anyone else need to do this in their modules/
> > classes, so now I'm wondering - has anyone else needed to do
> > this? It seems like this would be a common problem for any
> > shared Ruby library, so now I'm wondering why I *haven't* run
> > into this before.
>
> As things get sufficiently, complex, I think that something like
> this might be reasonable. Prawn is edging on needing some support
> for avoiding name clashes, since it carries a lot of internal state
> in the Document class and utilizes many mixins.
> I'm not sure if this is the convention we'll use, but it's one
> possibility.

Gregory, that's interesting. Maybe any Ruby library that reaches
sufficent mass use will run into this problem.

But I think the underscore doesn't really solve the problem, right?

Let's say you use @_file in your module that I include. You probably
use #nodoc# around it so I don't even see it in the rdocs. So then my
class I'm about to do @file, but I think, someone might derive from my
class, so I'd better call it @_file. Collision again.

So I say, let's not use the hard-to-read underscores, and document
ivars in the rdocs like everything else.

Of course, it's not that I like my solution either... :frowning: I'm just
not seeing how adding underscores solves the problem.

Jeff

But I agree, @_whatever is ugly and I'm not sure I will introduce it
into Prawn. I just understand why the Rails guys did it after having
a bit of direct experience.

...

I'm about to do some major refactoring in Prawn in the near future.
I might play with these thoughts and see where they lead. If I shake
anything loose that's worth sharing, I'll write it up on the RBP blog.

Sorry for being a bit late to this thread.
Date (from the 2008-01-17 version?) seems to use @__ca__
as a "hidden" cache for some values:
   def initialize(ajd=0, of=0, sg=ITALY)
     @ajd, @of, @sg = ajd, of, sg
     @__ca__ = {}
   end
Are there any reasons you can't use a hash like that,
or maybe use something like the code below?
Admittedly, the underlying problem isn't eliminated,
just reduced: one has to "agree" not to use @_
(or something similar if @_ is in use or "reserved" for
future use) for a "normal" attribute.
And things like @_.pa2 aren't pretty.
But one thing I like about Ruby is that some things
aren't forbidden, just discouraged by looking ugly
and/or being difficult, so you must think carefully
before using them.

class ExampleClass
  class PrivateAtts
    attr_accessor :private_attribute_1, :pa2
  end
  def initialize() ; @_ = PrivateAtts.new ; end
  def a_method( n ) ; @_.pa2 = n ; end
  def another_method() ; @_.pa2 ; end
end

ex = ExampleClass.new
#=> #<ExampleClass:0x2650600 @_=#<ExampleClass::PrivateAtts:0x26505e0>>
ex.a_method(42)
#=> #<ExampleClass:0x2650600 @_=#<ExampleClass::PrivateAtts:0x26505e0 @pa2=42>>
ex.another_method()
#=> 42

路路路

On Wed, Jan 13, 2010 at 4:24 AM, Gregory Brown <gregory.t.brown@gmail.com> wrote: