Simple Question About Deleting Instances

zdennis wrote:

I had to think about half a second, and then type for about 8 seconds.
Just copy and paste the code and put it in a file that you
require on your projects, and you won’t have to think. I will think for
you. Matz is busy solving bigger problems and conquering
better obstacles. So he doesn’t have to think about this, I will put my
brain to work for him.

class Class
def attr_class_accessor arg
instance_eval “class << self ; attr_accessor :#{arg} ; end”
end

def attr_class_reader arg
  instance_eval "class << self ; attr_reader :#{arg} ; end"
end

def attr_class_writer arg
  instance_eval "class << self ; attr_writer :#{arg} ; end"
end

end

If you feel this stronlgy about your desire to simplify this, perhaps
you should submit it as an RCR, http://www.rcrchive.net. I
am not saying I think your idea to simplify this into a builtin part of
ruby is a bad thing, but I think that you should not
abolish your ability to think. Ruby gives you power, use it. And if you
think it can be made better, submit a patch or submit an RCR.

Matz gives you the power to influence the langauge, I challenge you to
do so.

It’s not so much that I feel strongly as much as that it perplexes me. I
guess I just wanted to make sure my meds haven’t been replaced with
crazy pills.

I thought of this, too: isn’t it odd that you can define class variables
in a definition of how instances of a class should work, but you can’t
define their accessors? It seems inconsistent. If it’s agreed that this
is inconsistent, I’ll post something to the site you mentioned, but if
it’s that way for a reason, I’ll just take your much appreciated advice,
learn that much more, and be that much less of a newbie.

Austin Z. wrote:

So using attr_accessor doesn’t declare a variable; it declares a pair of
methods that access and may instantiate a variable, but doesn’t have to.
And that is why doing “attr_accessor :@var” really wouldn’t be
appropriate.

I guess to put my question simply, why is there a single context in
which I can define class variables but not class methods (accessors for
these variables)? Shouldn’t the two be handled in the same context /
scope / block / area-of-code?

On 4/7/06, Nathan O. [email protected] wrote:

zdennis wrote:
[…]
newbie.
I’m not sure you’re clear on the concept (I don’t mean that meanly).

Consider:

class Foo
@bar = 5 # the instance variable @bar of Foo:class (1)
@@bar = 5 # the class variable @bar of Foo:class (2)

def initialize
  @bar = 5  # the instance variable @bar of a Foo instance. (3)
end

end

When you do:

class Foo
class << self
attr_accessor :bar
end
end

You are accessing (1). (2) is not affected.

I addressed some of the reasons why you wouldn’t simply do:

attr_accessor :@var

in my article on Symbols in January (on the O’Reilly Ruby blog), but
remember that attr_accessor defines methods. There’s no difference
between the types of code here. In fact, if you run “ruby -w” on this
code, you’ll get warnings about method redefinitions for the latter two.

class Foo
attr_accessor :bar

def bar; @bar; end
def bar=(x); @bar = x; end

end

Jumping back to the Pickaxe:

class Song
attr_accessor :duration # in seconds

def minutes=(x); @duration = (x * 60).to_i; end
def minutes; @duration / 60; end

end

s = Song.new
s.duration = 60
s.minutes # => 1
s.minutes = 2.3
s.duration # => 138

For documentation purposes, I’ll sometimes do the following:

class Song
# The duration of the song in seconds.
attr_accessor :seconds
# The duration of the song in minutes.
attr_accessor :minutes
remove_method :minutes, :minutes=
def minutes=(m) # :nodoc:
@seconds = (x * 60).to_i
end
def minutes # :nodoc:
@duration / 60
end
end

So using attr_accessor doesn’t declare a variable; it declares a pair of
methods that access and may instantiate a variable, but doesn’t have to.
And that is why doing “attr_accessor :@var” really wouldn’t be
appropriate.

-austin

Austin Z. wrote:

No. To clarify my statement:

#attr_accessor creates a pair of instance methods that access and
may instantiate an instance variable, but don’t have to.

Instance variables are always bound to a particular value of self. (I’m
not quite sure where class variables reside.)

“class Foo”, “class << self”, and “def myself” all change scope and the
meaning of “self” in that scope.
Way, way over my head, but that probably has something to do with the
two-year-old demanding that I stop reading and start wrestling with him.
I’ll sleep on this one. Thanks! I think I might have a shot at
understanding this one in the morning.

On 4/7/06, Nathan O. [email protected] wrote:

Austin Z. wrote:

So using attr_accessor doesn’t declare a variable; it declares a pair
of methods that access and may instantiate a variable, but doesn’t
have to. And that is why doing “attr_accessor :@var” really
wouldn’t be appropriate.
I guess to put my question simply, why is there a single context in
which I can define class variables but not class methods (accessors
for these variables)? Shouldn’t the two be handled in the same context
/ scope / block / area-of-code?

No. To clarify my statement:

#attr_accessor creates a pair of instance methods that access and
may instantiate an instance variable, but don’t have to.

Instance variables are always bound to a particular value of self. (I’m
not quite sure where class variables reside.)

class Foo
p “#{self.inspect} (#{self.object_id})”
class << self
p “#{self.inspect} (#{self.object_id})”
def myself
p “#{self.inspect} (#{self.object_id})”
end
end
myself
def myself
p “#{self.inspect} (#{self.object_id})”
end
end
“Foo (23584680)”
“#Class:Foo (23584668)”
“Foo (23584680)”
=> nil
Foo.new.myself
“#Foo:0x2cfa7c8 (23581668)”
=> nil

So, within the scope of “class Foo”, self is a particular object (known
as Foo, oddly enough ;). Within the “class << self” inside of “class
Foo”, self is a wholy different object. Within the instance method
declared in “class << self”, self is once again the Foo object.

Calling “myself” from the scope of “class Foo” demonstrates this. I
could call Foo.myself can get the same result. What that shows is that
if I use @var inside of the scope of “class Foo”, I’m actually using
an instance variable inside of that object (of type Class).

Where you seem to be having problem is that unlike other languages,
a simple declaration in Ruby isn’t. Declaration is execution. There is
no “compile” stage followed by a “run” stage. The two happen together
(as demonstrated above).

“class Foo”, “class << self”, and “def myself” all change scope and the
meaning of “self” in that scope.

Does that help?

-austin

On 4/8/06, Jeff C.man [email protected] wrote:

“class Foo”, “class << self”, and “def myself” all change scope and
the meaning of “self” in that scope.
Way, way over my head, but that probably has something to do with the
two-year-old demanding that I stop reading and start wrestling with
him. I’ll sleep on this one. Thanks! I think I might have a shot at
understanding this one in the morning.
As traditional as they are, for me the Foo/bar style examples can be
confusing because they give no context.

Fair enough. However, let me point out that you showed something
different than I showed. I deliberately didn’t get into class
variables (@@var) because the point I was making was solely about the
change of scope, and @@var is a little funny with scope (I personally
think it’s broken, and I simply don’t use them any more).

In many ways, the Pickaxe Song/Jukebox example is bad anyway; the
Jukebox should be keeping track of how many songs it has played, not
the Song class, which may be used by other Jukebox instances, and for
billing purposes, you don’t want those song counts commingled. :slight_smile:

In your example, you also didn’t give a definition for
Song::total_plays.

If, however, we were to accept the Pickaxe premise as valid, here’s what
I would do:

class Song
attr_accessor :name
attr_accessor :artist
attr_accessor :duration
attr_reader :plays

# Class instance variable
@total_plays = 0

class << self
  attr_reader :total_plays
end

# This could be in the class << self as def add_play...
def self.add_play
  @total_plays += 1
end

def initialize(name, artist, duration)
  self.name = name
  self.artist = artist
  self.duration = duration
  @plays = 0
end

def play
  self.class.add_play
  @plays += 1
  # play the song
end

end

@total_plays in the “class Song” scope belongs to the self that is
“class Song”. This is the same scope within “def self.add_play” or in
the method defined by “class << self; attr_reader :total_plays; end”.

-austin

Austin Z. wrote:

… a bunch of good stuff snipped …

Thanks for your corrections, Austin, I see your points.

I certainly didn’t mean to criticize your examples, I just felt like it
might help to bring the discussion to some concrete examples, as the
original poster seemed to have a confusion about the nature of class
versus instance variables, which IMO might be cleared up before the
higher-level discussion about scoping becomes useful.

Jeff

Nathan O. wrote:

Austin Z. wrote:

No. To clarify my statement:

#attr_accessor creates a pair of instance methods that access and
may instantiate an instance variable, but don’t have to.

Instance variables are always bound to a particular value of self. (I’m
not quite sure where class variables reside.)

“class Foo”, “class << self”, and “def myself” all change scope and the
meaning of “self” in that scope.
Way, way over my head, but that probably has something to do with the
two-year-old demanding that I stop reading and start wrestling with him.
I’ll sleep on this one. Thanks! I think I might have a shot at
understanding this one in the morning.

As traditional as they are, for me the Foo/bar style examples can be
confusing because they give no context.

The Pickaxe book gives a good example of the difference between instance
variables and class variables and how they can be useful. Perhaps this
is stuff you already know, but it can be helpful to cover it again.

In the Pickaxe example (paraphrasing the code), they’re making a Jukebox
application which plays songs and records the total number of plays of
each song, as well as the total number of songs played by the jukebox.

class Song
attr_accessor :name, :artist, :duration, :plays

@@total_plays = 0 # class variable, the total number of all songs
played by the jukebox

def initialize(name, duration)
self.name = name # using the accessor methods
self.artist = artist # using the accessor methods
self.duration = duration # using the accessor methods
plays = 0 # using the accessor methods
end

def play
@@total_plays += 1 # increase the total count
self.plays += 1 # increase the count for this song
# play the song
end
end

So if you do this:

so_what = Song.new(“So What”, “Miles Davis”, 9.24)

so_what.play
so_what.play
Song.total_plays #=> 2
so_what.plays #=> 2

penny_lane = Song.new(“Penny Lane”, “The Beatles”, 3.45)

penny_lane.play
penny_lane.play

Song.total_plays #=> 4
penny_lane.plays #=> 2

So the “@@total_plays” variable stores a value unique to the class of
Song, regardless of instances. And the instance variables store values
unique to each instance. The class variable can be “declared” or used
in the body of the class definition, but the instance variable should be
used in the body of a method.

I’m sure you know most of this, but hopefully it helps a bit.

Jeff C.man