Hey All,
If I run this script (ruby 1.8.2 (2004-07-29) [i386-mswin32] on
win2k):
# ---------------------------------------
require "net/http"
PROXYSERVER = "proxy.ghc.org"
PROXYPORT = 8080
my_array = ["rama", "lama", "ding"]
def someMethod
Net::HTTP.Proxy(PROXYSERVER, PROXYPORT).start("www.ruby-doc.org")
do |http|
my_array += ["dong"]
end
end
puts my_array
someMethod
# ---------------------------------------
I get this for output:
C:\>ruby httperr.rb
rama
lama
ding
httperr.rb:12:in `someMethod': undefined method `+' for nil:NilClass
(NoMethodEr
ror)
from httperr.rb:11:in `start'
from c:/program files/ruby/lib/ruby/1.8/net/http.rb:324:in
`start'
from httperr.rb:11:in `someMethod'
from httperr.rb:18
Can anybody tell me why my backtrace seems to implicate http.rb? I
was chasing my tail for quite a bit on that one. (At one point I
figured there was just something wrong w/http.rb on windows & was
regex searching the backtrace for "http.rb:324" to see if I could
disregard the error. Silly me.)
well - in a sense you ARE inside http.rb. see, the 'start' method takes a
block, which is an anonyous callback, and calls it for you. eg.
harp:~ > cat a.rb
def call_the_callback
yield
end
call_the_callback do
raise 'foobar'
end
harp:~ > ruby a.rb
a.rb:6: foobar (RuntimeError)
from a.rb:5:in `call_the_callback'
from a.rb:5
and here we see the same thing:
- the error starts from line 6 where the raise statement is
- but this code is actually called from inside 'call_the_callback'
in your case the error is on line 12 in your program, but this code itself has
been passed to, and is being called from, the 'start' method of httpd.rb on
line 324 of that file.
a stacktrace is a nesting of all method calls you are in - starting from
innermost:
harp:~ > cat a.rb
def c
raise 'here'
end
def b
c
end
def a
b
end
a()
harp:~ > ruby a.rb
a.rb:2:in `c': here (RuntimeError)
from a.rb:5:in `b'
from a.rb:8:in `a'
from a.rb:11
what is causing this to be even a bit more confusing is that the argument to
some of the methods in your program are bits of code themselves - callbacks,
blocks, whatever you want to call them...
[And I'm still wondering why my_array is not visible inside
someMethod. If I make the var name @my_array all is well, which is
also confusing since I'm not in a class def, so why should I need an
instance var...]
in ruby you are ALWAYS in a class def. it's as if you start every script with
class Object
...
this makes ruby seems imperative in that you can say things like
puts 'foobar'
but you are not calling some global puts, you are calling Object#puts (or
maybe it's Kernel#puts i forget). the point is that ruby is organized so that
you are inside an object which has a whole suite of useful methods in it, so
many you can forget you are in an object. this is how ruby maintains itself
to be completely object oriented without making jump through hoops like java
does when you want to just print something to the terminal - in java you must
do everything from within a class so you have to write a class just to write
'foobar' to the screen.
so, the reason your program runs with @array is that you've made an instance
variable of class Object but, for ruby, this is pretty close to making a
global variable since everything is inside Object already. in general i'd say
'don't do that'. if you don't make the variable in instance variable of class
Object then it's just scoping preventing you from seeing the variable, it's as
if you'd written this in c
void()foobar{ x = 42; }
main(){ int x; foobar(); }
it's just not going to work since x is not in the scope of foobar. likewise
my_array is not in the scopy of the start method. you have some choices such
as
make the varible in scope for the start method:
harp:~ > cat a.rb
require "net/http"
def someMethod
my_array = ["rama", "lama", "ding"]
Net::HTTP::start("www.ruby-doc.org") do |http|
my_array += ["dong"]
end
puts my_array
end
someMethod
harp:~ > ruby a.rb
rama
lama
ding
dong
or, if you want to use it outside someMethod but don't want to pollute Object
with all sorts of instance (and sort of global) variables then make a class,
after all classes a bundles of state and methods that affect that state or
other objects, eg:
harp:~ > cat a.rb
require "net/http"
class MyClass
attr :array
def initialize
@array = ["rama", "lama", "ding"]
end
def some_method
Net::HTTP::start("www.ruby-doc.org") do |http|
@array += ["dong"]
end
end
end
mc = MyClass::new
mc.some_method
p mc.array
harp:~ > ruby a.rb
["rama", "lama", "ding", "dong"]
hope that helps.
kind regards.
-a
···
On Fri, 5 Nov 2004, Roy Pardee wrote:
--
EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki
===============================================================================