What *are* variables? Which are nil now?

  • Thread starter Hugh Sasse Staff Elec Eng
  • Start date
H

Hugh Sasse Staff Elec Eng

Reading about reflection, ObjectSpace will give you the objects in
your system, possibly selected by Class. Fine. It won't tell you
which variables are associated with them. You can trace on global
variables, you can look at instance variables, but how can you get
information about all variables? What *is* a variable, exactly, come
to that? It works like a sticky label so you can have two on the
same object, but are the variables themselve objects in ruby? Can I
twist ObjectSpace's arm to tell me about them?

Why have I run into this now?

I'm getting
#<TypeError: failed to convert nil into Array>
raised by a program where
rescue => e
p e, caller
gives some line numbers with an each keyword, where the code looks like
raise "@b1 is nil" if @b1.nil
@b1.each { |bf|
so I know that @b1 is not nil when it gets here. The each method is
one I wrote, so I'd expect it to blow up in there, with an
associated line number.

Can I get ruby to tell me all things that point at the one Nil
object in the universe, at the present time?

This is with 1.6.8 and with 1.8.0

Thank you,
Hugh
 
G

Gavin Sinclair

Reading about reflection, ObjectSpace will give you the objects in
your system, possibly selected by Class. Fine. It won't tell you
which variables are associated with them. You can trace on global
variables, you can look at instance variables, but how can you get
information about all variables? What *is* a variable, exactly, come
to that? It works like a sticky label so you can have two on the
same object, but are the variables themselve objects in ruby? Can I
twist ObjectSpace's arm to tell me about them?

Variables are not objects; it's as simple as that. They are sticky
notes. You can get a list of local variables in any scope with
Kernel::local_variables. Then you can eval them to find out what they
are.

You can get a list of variables in other scopes as well. I have a
marvellous proof for this, which this margin is too small to contain.

Gavin
 
H

Hugh Sasse Staff Elec Eng

Variables are not objects; it's as simple as that. They are sticky
notes. You can get a list of local variables in any scope with
Kernel::local_variables. Then you can eval them to find out what they

thanks, I missed that one.
are.

You can get a list of variables in other scopes as well. I have a
marvellous proof for this, which this margin is too small to contain.

I seem to be needing large margins for my errors, I'll send you one!
:) I'd like to know how to extract this info from Ruby. It might
not have helped in my case though, but would be generally good to
have.
Thank you,
Hugh
 
G

Gavin Sinclair

[Hugh:]
thanks, I missed that one.


I seem to be needing large margins for my errors, I'll send you one! :)
I'd like to know how to extract this info from Ruby. It might not have
helped in my case though, but would be generally good to
have.

Heh, all I had in mind was this: if you can get a Binding to another
scope, then you can execute "local_variables" in that binding. To wit:

def foo
a = 1
b = 2
c = 3
return binding
end

b = foo # <Binding:0x10187e70>
local_variables # ["_", "b"]
eval "local_variables", b # ["a", "b", "c"]
eval "a", b # 1
eval "b", b # 2
eval "b" # <Binding:0x10187e70>

I don't know if/how you can get a binding to another scope without
explicitly arranging it. Not through Kernel::caller, for better or worse.

Gavin

# Now, who can tell me what that "_" local variable is? Extra points for
# telling me why I should have known all along.
 
J

Joel VanderWerf

Gavin said:
# Now, who can tell me what that "_" local variable is? Extra points for
# telling me why I should have known all along.

Must be an irb thing. I don't see it when executing your code in ruby
directly, only in irb.
 
G

Gavin Sinclair

<[email protected]>







<Pine.GSO.4.53.0309110033360.26201@neelix>
<[email protected]>
<[email protected]>
X-ML-Name: ruby-talk
X-Mail-Count: 81687
X-MLServer: fml [fml 4.0.3 release (20011202/4.0.3)]; post only (anyone can post)
X-ML-Info: If you have a question, send e-mail with the body
"help" (without quotes) to the address (e-mail address removed);
help=<mailto:[email protected]?body=help>
X-Mailer: SquirrelMail (version 1.2.7)
X-Priority: 3
Importance: Normal
X-MSMail-Priority: Normal
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Precedence: bulk
Lines: 19
List-Id: ruby-talk.ruby-lang.org
List-Software: fml [fml 4.0.3 release (20011202/4.0.3)]
List-Post: <mailto:[email protected]>
List-Owner: <mailto:[email protected]>
List-Help: <mailto:[email protected]?body=help>
List-Unsubscribe: <mailto:[email protected]?body=unsubscribe>
X-Spam-Status: No, hits=-4.7 required=5.0
tests=AWL,BAYES_01,IN_REP_TO,MISSING_MIMEOLE,
MISSING_OUTLOOK_NAME,QUOTED_EMAIL_TEXT,REFERENCES,
REPLY_WITH_QUOTES
version=2.55
X-Spam-Level:
X-Spam-Checker-Version: SpamAssassin 2.55 (1.174.2.19-2003-05-19-exp)
Must be an irb thing. I don't see it when executing your code in ruby
directly, only in irb.

Ah, interesting. My instinct is to ask: "how can irb inject a local
variable into *my* local context?"

I think I've seen code where "_" is used as a parameter in a block,
signifying that we're not interested in that value. For instance:

hash.map { |_, value| f(value) }

Gavin
 
R

Robert Klemme

Hugh Sasse Staff Elec Eng said:
Reading about reflection, ObjectSpace will give you the objects in
your system, possibly selected by Class. Fine. It won't tell you
which variables are associated with them. You can trace on global
variables, you can look at instance variables, but how can you get
information about all variables? What *is* a variable, exactly, come
to that? It works like a sticky label so you can have two on the
same object, but are the variables themselve objects in ruby? Can I
twist ObjectSpace's arm to tell me about them?

Why have I run into this now?

I'm getting
#<TypeError: failed to convert nil into Array>
raised by a program where
rescue => e
p e, caller
gives some line numbers with an each keyword, where the code looks like
raise "@b1 is nil" if @b1.nil
@b1.each { |bf|
so I know that @b1 is not nil when it gets here. The each method is
one I wrote, so I'd expect it to blow up in there, with an
associated line number.

There are two issues with the line "raise "@b1 is nil" if @b1.nil?":

1. The test is inappropriate, what you really want is to ensure that the
obj referred to by @b has method "each". So these are better alternatives
(but see issue 2):

raise "Wrong @b1" unless @b1.kind_of? Enumerable
raise "Wrong @b1" unless @b1.respond_to? :each

2. Btw, generally it's superfluous to include the explicite test and raise
since if the instance referred to by @b does not have an "each" method the
code will blow anyway with an NoMethodError. So omitting this test is
shorter and cleaner.
Can I get ruby to tell me all things that point at the one Nil
object in the universe, at the present time?

Well, you could do this

unless @b1.respond_to? :each
p @b1 # prints info about @b1
puts @b1.class # print type
# print other informative stuff

raise "No each"
end

or use the debugger.

But as I said before, generally this is not a too good idea.

Regards

robert
 
H

Hugh Sasse Staff Elec Eng

You can get a list of variables in other scopes as well. I have a
marvellous proof for this, which this margin is too small to contain.
[...]
I'd like to know how to extract this info from Ruby. It might not have

Heh, all I had in mind was this: if you can get a Binding to another
scope, then you can execute "local_variables" in that binding. To wit:

Oh, *nice*! Yes, and I can roll that into the exception object I
throw.

Thank you
Hugh
 
H

Hugh Sasse Staff Elec Eng

There are two issues with the line "raise "@b1 is nil" if @b1.nil?":

1. The test is inappropriate, what you really want is to ensure that the

This was debugging code, added after getting the error. I wanted to
be sure that the @b1 was the thing that was becoming nil. It wasn't
obj referred to by @b has method "each". So these are better alternatives
(but see issue 2):

raise "Wrong @b1" unless @b1.kind_of? Enumerable
raise "Wrong @b1" unless @b1.respond_to? :each

Those would avoid an "undefined method" error, which was not what I
was getting. They are right for checking each though
I was getting "\n# said:
2. Btw, generally it's superfluous to include the explicite test and raise

Yes, it was not in the original program.
Well, you could do this
[ p @b1 # prints info about @b1 etc]
or use the debugger.

Yes, that produced the same message in some very odd places, but no
variables showed up with the error because it was in the middle of
an expression.
But as I said before, generally this is not a too good idea.

Regards

robert

Thank you,
Hugh
 

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
474,125
Messages
2,570,748
Members
47,302
Latest member
MitziWragg

Latest Threads

Top