From: Stefano Crocco Date: 2008-07-23T19:18:12+09:00 Subject: Re: circular 'require' On Wednesday 23 July 2008, Shadowfirebird wrote: > Hi, > > I'm new to ruby and I'm really enjoying it. However, there is one > thing... > > I gather from this list and my poor efforts that ruby does not like > files that 'require' each other circularly. I can find nothing in the > documentation about this, though; in fact, the description of require > seems to actually rule it out. Can anyone explain what is going on > here? > > (This happens in 1.8 and 1.9 and JRuby 1.0. So it's definitely me, > not Ruby, that has the problem.) > > > To flesh things out a little: > > 'require' is supposed to load files, unless they have been already > loaded. It stores an array of loaded files in $" for this purpose. > > Okay, suppose we have two programs in two different files: > > # test1.rb > require "test2.rb" > class One > def self.testone(); Two.whoistwo; end > def self.whoisone(); puts "class one"; end > end > > # test2.rb > require "test1.rb" > class Two > def self.testtwo(); One.whoisone; end > def self.whoistwo(); puts "class two"; end > end > > >ruby -w test1.rb > > ./test1.rb:4: unititialized constant Two (NameError) > > Why does this happen? I would have thought that test1 would load > test2; then test2 would go to load test1 but find it already loaded. > Apparently what happens is that test2 doesn't get loaded at all. The required file is added to $" only after its contents have been processed, so when the line require 'test1.rb' is executed, the file 'test1.rb' hasn't as yet inserted into $". To be more specific, here's what happens when the line require 'test1.rb' is executed: * the file test1.rb is read and parsed * starts the execution of test1.rb * the line require 'test2.rb' is executed. This means: * the file test2.rb is read and parsed * starts the execution of test2.rb * the line require 'test1.rb' is executed. This means: * the file test1.rb is read and parsed * starts the execution of test1.rb * the line require 'test2.rb' is executed. This means: ... As you can see, this leads to an endless loop. Can I ask you why do you need these circular requires? It's a situation which seldom happens using ruby. Also, using require, you don' need to specify the .rb extension. I hope this helps Stefano