From: Ara.T.Howard@... Date: 2004-11-06T09:13:42+09:00 Subject: Re: nuby sanity check--do I have a right to be confused by this error msg? On Fri, 5 Nov 2004, Roy Pardee wrote: > 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 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 -- =============================================================================== | 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 ===============================================================================