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?
irb(main):004:0> class B
irb(main):005:1> def foo
irb(main):006:2> @b1 =
irb(main):007:2> raise “@b1 is nil” if @b1.nil?
irb(main):008:2> @b1 = nil
irb(main):009:2> raise “@b1 is nil” if @b1.nil?
irb(main):010:2> @b1.each { |e| print “.” }
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> B.new.foo
RuntimeError: @b1 is nil
from (irb):9:in `foo’
from (irb):13
irb(main):014:0>
Is there a chance that @b1 is becoming nil between your test and the each
because the program is threaded?
As far as I know, there’s no way to know what variables (labels) are
referring to what values (objects).
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
···
On Thursday, September 11, 2003, 4:00:10 AM, Hugh wrote:
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?
“Hugh Sasse Staff Elec Eng” hgs@dmu.ac.uk schrieb im Newsbeitrag
news:Pine.GSO.4.53.0309101847560.23363@neelix…
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?”:
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):
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.
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.
“Hugh Sasse Staff Elec Eng” hgs@dmu.ac.uk schrieb im Newsbeitrag
news:Pine.GSO.4.53.0309101847560.23363@neelix…
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?”:
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):
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#<TypeError: failed to convert nil to Array>”
Btw, generally it’s superfluous to include the explicite test and raise
Yes, it was not in the original program.
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
[ 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.
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.
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
Assuming that @dirs is an Array, Array.+ tries to convert the argument
(which is the result of the expr right to the “+”) to an Array and throws
the exception
I think he’s looking for something more like this:
VariableSpace.each_pointing_to(nil) do |var|
Do something with “var”, which is probably some kind of
object-oriented representation of a variable in memory.
end
Yes, though I suspected that this might not be possible: ruby itself
doesn’t do much with our ‘sticky note’ variable names because it
doesn’t need that sugar.
No way to do anything even close to this that I know of.
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.
Assuming that @dirs is an Array, Array.+ tries to convert the argument
(which is the result of the expr right to the “+”) to an Array and throws
the exception
Agreed, but is the point where the message is generated accessible,
such that I can interpose something? This Array#+ isn’t calling
arg.to_a as far as the above shows…
Assuming that @dirs is an Array, Array.+ tries to convert the argument
(which is the result of the expr right to the “+”) to an Array and
throws
the exception
Agreed, but is the point where the message is generated accessible,
such that I can interpose something? This Array#+ isn’t calling
arg.to_a as far as the above shows…
You can
redefine Array#+
look into the sources for Array#+
But isn’t the stack trace good enough for catching the error you got?
Agreed, but is the point where the message is generated accessible,
such that I can interpose something? This Array#+ isn't calling
arg.to_a as far as the above shows...
“Hugh Sasse Staff Elec Eng” hgs@dmu.ac.uk schrieb im Newsbeitrag
news:Pine.GSO.4.53.0309111033140.26256@neelix…
Agreed, but is the point where the message is generated accessible,
such that I can interpose something? This Array#+ isn’t calling
arg.to_a as far as the above shows…
You can
redefine Array#+
That occurred to me later. Originally I could not determine it was
that line though.
look into the sources for Array#+
Yes, I amy do that,
But isn’t the stack trace good enough for catching the error you got?
No: the first thing in the stack trace was that ‘@b1.each {|bf|’ line
Agreed, but is the point where the message is generated accessible,
such that I can interpose something? This Array#+ isn’t calling
arg.to_a as far as the above shows…
No, it call #to_ary
I can’t see that listed either in the windows copy of the Pickaxe,
or in nil,methods.