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

  • Thread starter Michael Winterstein
  • Start date
M

Michael Winterstein

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).
 
M

Marnen Laibow-Koser

Michael said:
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. :)
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,
 
D

David Masover

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).
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.
 
B

Benoit Daloze

[Note: parts of this message were removed to make it a legal post.]

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?
 
M

Michael Winterstein

Benoit said:
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
 
P

pharrington

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.
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)
 
R

Rick DeNatale

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)

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.

--=20
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
 
R

Ralph Shnelvar

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.
 
P

pharrington

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.
 

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

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top