why does block know about one instance variable and not the other?

A

anne001

I can't find what the problem is with @foundinfo: since it is defined
outside a block, the block should find it no? @item is defined outside
the second block and that second block finds it. What is @item and
@foundinfo different?

Do I have a typo I don't see, or it there a principle of the thing?

Here is my simplified code with debugging puts

class Linear
@foundinfo=Hash.new
p " 1. debugging @foundinfo created"
p @foundinfo.class #this is ok

def run

data="hello dud"
data.split(/</).each do |line|
line =~ /d(.)d/
@item=$1
p "2. debugging, @foundinfo found?"
p @foundinfo.class # this is not ok, @foundinfo not found

lines="and so on and some more"
lines.split(/</).each do |chunk|
p "3. debugging, @item found?"
p @item #this is ok, @item found
p "3. debugging, @foundinfo found?"
p @foundinfo.class # this is still not ok, @foundinfo
not found
end # end do chunk
end # end do line
end # end run

end # end class

a=Linear.new
a.run
 
D

dblack

Hi --

I can't find what the problem is with @foundinfo: since it is defined
outside a block, the block should find it no? @item is defined outside
the second block and that second block finds it. What is @item and
@foundinfo different?

Do I have a typo I don't see, or it there a principle of the thing?

There's a principle:

Whenever you see this:

@var

you are seeing an instance variable that belongs to whatever object is
"self" at that moment in runtime.

Now, watch this:

class C
puts self
def x
puts self
end
end

C.new.x

What you get from this code is:

C
#<C:0x325648>

In other words, in the top level of a class definition block, "self"
is the class object itself (C, in this case). Inside a method
definition -- that is, when that method is eventually executed --
"self" is the instance that's executing the method: hence the
"instance of C" inspect string on the second line.

It follow that when you do this:

class C
@var = 1
def x
@var = 2
end
end

you're dealing with two separate, unrelated instance variables, owned
by different objects.


David

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
http://www.manning.com/black => RUBY FOR RAILS, the Ruby book for
Rails developers
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
(e-mail address removed) => me
 
A

anne001

Thank you for your response.

It did occured to me sometime after I wrote the post that the
difference between the two instance variables was that one was outside
the define and the other inside. A look at
http://www.ruby-doc.org/docs/UsersGuide/rg/instancevars.html
and other examples, shows that the instance variable is always defined
in a method without saying why.

So I was very glad to find your response.

I thought of an instance as a copy of the class. so implicitely I
assumed it would get a copy of an instance variable. Maybe I should
think of an object as an inheritance of methods: So it inherits
methods, not variables.

But if that was the rule, it would not work for constants either
http://www.ruby-doc.org/docs/UsersGuide/rg/constants.html
in the example there, it would get a method and have no idea what the
constants were.

your example helped clarify what is going on.

class C
puts self
@var = 1
puts self
def x
puts self
@var = 2
end
end
p "create new instance of C"
y= C.new
p y
p "run method which creates an instance variable"
y.x
p y

class D
puts self
@@var = 1
puts self
def x
puts self
@@var = 2
end
end
p "create new instance of D"
y= D.new
p y
p "run method which creates an instance variable"
y.x
p y

In class C, running x adds @var to the object, but in D, running x does
not add @@var.

@var is an instance variable that belongs to whatever object is
"self" at that moment in runtime.

QUESTION: If that is the case, why does puts self not append @var=1 to
object C the way it
appends @var=2 to the instance?
#<C:0x25b58 @var=2>

In any case, the code in C outside of the methods is only run once when
the new method is called, and the object is C. OK. I had not thought of
it that way.

So is this an ok way to think about objects:
1. Objects inherit methods
2. The variable environment includes, read access to Class constants,
r/w to @@var and r/w to global variables
2. @var become local to whatever object is self at the moment they are
created.
 
M

Marcin Mielżyński

anne001 said:
I thought of an instance as a copy of the class. so implicitely I
assumed it would get a copy of an instance variable. Maybe I should
think of an object as an inheritance of methods: So it inherits
methods, not variables.

Instance of a class is not a copy of it. Classes are somewhat templates
for instances, they define what methods and variables their instances
will have. But since a Class in Ruby is also an object it can have
instance variable as well!.
In class C, running x adds @var to the object,

As it should do

but in D, running x does
not add @@var.
@@var is a special variable that is shared between class and it's
instances (so there is only one @@var, no matter how many instances
there are).
@var is an instance variable that belongs to whatever object is
"self" at that moment in runtime.

No, self is different in class context and instance context.
QUESTION: If that is the case, why does puts self not append @var=1 to
object C the way it
appends @var=2 to the instance?
#<C:0x25b58 @var=2>

Class objects have different default implementation of inspect method,
so they are printed differently using p. There is a way to query object
about their variables:

p C.instance_variable_get("@var")
-> 1
p y.instance_variable_get("@var")
-> 2

In any case, the code in C outside of the methods is only run once when
the new method is called, and the object is C. OK. I had not thought of
it that way.

So is this an ok way to think about objects:
1. Objects inherit methods

Nope, classes define methods which in turn will be available to their
instances upon construction
2. The variable environment includes, read access to Class constants,
r/w to @@var and r/w to global variables
Again, depends on the context (receiver aka self)
2. @var become local to whatever object is self at the moment they are
created.

I've never considered instance variables to be local to their instances
- but in a way, yes.

lopex
 
D

dblack

---2049402039-1736991851-1152493379=:20343
Content-Type: MULTIPART/MIXED; BOUNDARY="-2049402039-1736991851-1152493379=:20343"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

---2049402039-1736991851-1152493379=:20343
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi--

No, self is different in class context and instance context.

Right -- but that doesn't make what anne001 said wrong. When you see
@var, you're seeing an instance variable belonging to self. That's
true whether self is a class object or some other kind of object.


David

--=20
http://www.rubypowerandlight.com =3D> Ruby/Rails training & consultancy
http://www.manning.com/black =3D> RUBY FOR RAILS, the Ruby book for
Rails developers
http://dablog.rubypal.com =3D> D[avid ]A[. ]B[lack's][ Web]log
(e-mail address removed) =3D> me
---2049402039-1736991851-1152493379=:20343--
---2049402039-1736991851-1152493379=:20343--
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top