Local variables can't be accessed from outside, right?

Hi, I’ve been trying to figure out metaprogramming and I’ve mostly got
it figured out, but in doing so I ran across this example:

class A
def initialize
@a = 11
@@a = 22
a = 33
end
@a = 1
@@a = 2
a = 3
end

This was given as a posed question (can you access all the variables)
and a particular order of the output was given (specifically, 1 2 3 11
22 33). Getting at the instance variables, and even the class variables
doesn’t seem that hard to me. But it seems to me there’s no way to get
at the local variable a’s. The way it was asked makes me think it might
be possible, but I’m reasonably sure it isn’t.

However, I’m fairly new to Ruby and just wrapping my mind around the
metaprogramming ideas and realize I could easily be missing something.

I think a trick like puts A.new would be a lame solution, as would
finding it somehow in memory after the class definition end statement
(though that might be interesting to know if Ruby can do that).

Michael W. wrote:

Hi, I’ve been trying to figure out metaprogramming and I’ve mostly got
it figured out, but in doing so I ran across this example:

class A
def initialize
@a = 11
@@a = 22
a = 33
end
@a = 1
@@a = 2
a = 3
end

This was given as a posed question (can you access all the variables)
and a particular order of the output was given (specifically, 1 2 3 11
22 33). Getting at the instance variables, and even the class variables
doesn’t seem that hard to me. But it seems to me there’s no way to get
at the local variable a’s. The way it was asked makes me think it might
be possible, but I’m reasonably sure it isn’t.

However, I’m fairly new to Ruby and just wrapping my mind around the
metaprogramming ideas and realize I could easily be missing something.

I think a trick like puts A.new would be a lame solution,

Well, it would be the only solution to a lame question. :slight_smile:

finding it somehow in memory after the class definition end statement
(though that might be interesting to know if Ruby can do that).

Sort of. Remember, a class definition is executable code. Does that
give you an idea? It should.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Friday 27 November 2009 11:56:43 pm Michael W. wrote:

@@a = 2
a = 3
end

This was given as a posed question (can you access all the variables)
and a particular order of the output was given (specifically, 1 2 3 11
22 33).

I think a trick like puts A.new would be a lame solution,

That actually wouldn’t work, though I can see why you think it’d be
lame.

Anyway, as far as I know, there are only a few ways to access a local
variable:

You could define a= – for example,

def a=(value)
puts a
end

The problem is, I can’t actually get this to work reliably. It really
seems
like assignment of this kind would only work if you did

self.a = 33

So, with that discarded, I don’t think it’s possible to get access to
these
local variables with the class as written, at least not cleanly. You
could
probably figure out (programatically) where the class is defined, and
then
parse the source.

Other than that, the only way I know of getting at local variables is
through
the binding object, which you’d have to get either from inside the code,
or
from something called from that code – but that class doesn’t seem to
call
any methods from anywhere you care about, so that doesn’t work.

class_local_a = class A
def initialize
@a = 11
@@a = 22
a = 33
end
@a = 1
@@a = 2
a = 3
end

p A.instance_variable_get(:@a) #ok

p A.class_variable_get(:@@a) if RUBY_VERSION > ‘1.9’
class A; p @@a end if RUBY_VERSION < ‘1.9’

a little tricky, sure

p class_local_a

p A.new.instance_variable_get(:@a)

p A.class_variable_get(:@@a) if RUBY_VERSION > ‘1.9’
class A; p @@a end if RUBY_VERSION < ‘1.9’

p A.new.method(:initialize).call

I didn’t find other way to get the result of class A … end like a if
or
case result.
Very weared a class’ instance variable(1)
Does it have any interest?

2009/11/28 David M. [email protected]

Benoit D. wrote:

I didn’t find other way to get the result of class A … end like a if
or
case result.
Very weared a class’ instance variable(1)
Does it have any interest?

No, it’s just an example for learning about metaprogramming. Which is
why it seems strange; the local variables can only be ‘accessed’ because
they happen to be return values.

I did learn something I didn’t know, however :

class A
puts “Local variables: #{local_variables}”
puts “Instance variables: #{instance_variables}”
a = 5
@a = 6
puts “Local variables: #{local_variables}”
puts “Instance variables: #{instance_variables}”
end

Local variables: a
Instance variables:
Local variables: a
Instance variables: @a

So local variables exist in some ethereal void after the code is scanned
but before they can be used; not so with instance variables. That makes
some sense. But this also lets you do this eval weirdness.

class B
puts “#{local_variables.first} = #{eval(local_variables.first)},
which is a #{eval(local_variables.first).class}”
eval(local_variables.first + “=2”)
puts “#{local_variables.first} = #{eval(local_variables.first)},
which is a #{eval(local_variables.first).class}”

puts #{a} if a    #=> NameError: undefined local variable or method 

‘a’ for B:Class
a = 4
puts “#{local_variables.first} = #{eval(local_variables.first)},
which is a #{eval(local_variables.first).class}”
end

With the error commented out, this gives:
a = , which is a NilClass
a = 2, which is a Fixnum
a = 4, which is a Fixnum

On Sat, Nov 28, 2009 at 2:30 PM, pharrington [email protected]
wrote:

was defined)
Actually, for MRI, at compile time a local gets assigned an index
which is used to dereference an element of an array of local variables
pointed to by a structure called SCOPE there is a stack of these
scopes which grows and shrinks as methods and blocks are called and
returned…

The actual local variables need to be unique for each method
invocation or block evaluation.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On Nov 28, 1:15 pm, Michael W. [email protected]
wrote:

they happen to be return values.
end

Local variables: a
Instance variables:
Local variables: a
Instance variables: @a

So local variables exist in some ethereal void after the code is scanned
but before they can be used; not so with instance variables. That makes
some sense. But this also lets you do this eval weirdness.

From what I understand, this is because local variables are created
when code is parsed, not actually run (as method resolution would be
even more painful if the interpreter had to first search the object
tree for a particular instance method every time a new local variable
was defined)

p> From what I understand, this is because local variables are created
p> when code is parsed, not actually run (as method resolution would
be
p> even more painful if the interpreter had to first search the object
p> tree for a particular instance method every time a new local variable
p> was defined)

Ah! So local variables are created when parsed but instance and class
variables are created at execution!

I hope that’s right because a lightbulb just turned on.

On Nov 28, 3:46 pm, Ralph S. [email protected] wrote:

p> From what I understand, this is because local variables are created
p> when code is parsed, not actually run (as method resolution would be
p> even more painful if the interpreter had to first search the object
p> tree for a particular instance method every time a new local variable
p> was defined)

Ah! So local variables are created when parsed but instance and class
variables are created at execution!

I hope that’s right because a lightbulb just turned on.

Well its not exactly right (as Rick DeNatale explained) buts its a
simple way to picture what goes on.