From: "Michael T. Richter" Date: 2008-07-23T23:39:02+09:00 Subject: Re: circular 'require' --=-DN/6/TBkz7AAneaRIhEA Content-Type: text/plain Content-Transfer-Encoding: 7bit On Wed, 2008-07-23 at 22:48 +0900, Shadowfirebird wrote: > I found a very easy way around it. This is what bothers me. If it's > that easy, why doesn't require do it? Try my code with that: michael@isolde:~/junk$ cat test1.rb $" << "test1.rb" load("test2.rb") unless $".include?("test2.rb") class NeededInTest2 @@funny_stuff = NeededInTest1.new end michael@isolde:~/junk$ cat test2.rb $" << "test2.rb" load("test1.rb") unless $".include?("test1.rb") class NeededInTest1 @@funny_stuff = NeededInTest2.new end michael@isolde:~/junk$ ruby test1.rb ./test2.rb:4: uninitialized constant NeededInTest1::NeededInTest2 (NameError) from test1.rb:2:in `load' from test1.rb:2 The real solution remains a proper system of modules in Ruby. > # test1.rb > $" << "test1.rb" > load("test2.rb") unless $".include?("test2.rb") > class One < Two > def self.testone(); Two.whoistwo; end > def self.whoisone(); puts "class one"; end > end > > # test2.rb > $" << "test2.rb" > load("test1.rb") unless $".include?("test1.rb") > class Two > def self.testtwo(); One.whoisone; end > def self.whoistwo(); puts "class two"; end > end > > > On Wed, Jul 23, 2008 at 2:03 PM, Michael T. Richter > wrote: > > On Wed, 2008-07-23 at 20:39 +0900, Calamitas wrote: > > > >> test1.rb is executed twice, but what probably caused the error in the > >> OP's original program (the OP pared it down to a point where it > >> actually did "work") is the fact that "the rest of test1.rb" is > >> executed before "the rest of test2.rb". It can probably be solved by > >> doing "ruby -r test1.rb" instead, but that's icky. Generally, if I > >> *were* to use circular requires, I'd never put "executable code" in > >> either file, just "declarations". I don't use them though. Not anymore > >> after I've been bitten a few times. > > > > > > Here's what the OP was talking about, I suspect, taken down to its > > briefest possible example: > > > > > > $ cat test1.rb > > require 'test2' > > class NeededInTest2 > > @@funny_stuff = NeededInTest1.new > > end > > > > michael@isolde:~/junk$ cat test2.rb > > require 'test1' > > class NeededInTest1 > > @@funny_stuff = NeededInTest2.new > > end > > > > michael@isolde:~/junk$ ruby test1.rb > > ./test1.rb:3: uninitialized constant NeededInTest2::NeededInTest1 (NameError) > > from /home/michael/software/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' > > from /home/michael/software/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' > > from ./test2.rb:1 > > from /home/michael/software/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' > > from /home/michael/software/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' > > from test1.rb:1 > > > > > > This is the problem boiled down to its essence. There is no easy way > > out of this either that doesn't either a) mangle the architecture or b) > > fail. You can't use something like C/++'s "include guards" to get > > around this, nor can you use any kind of super-class elevation trick or > > the like. What would be needed to solve this issue would be for ruby to > > have a proper sense of modules and do linkage across those instead of > > treating the entire tree of requires as, in effect, one ginormous text > > file. > > > > -- > > Michael T. Richter (GoogleTalk: > > ttmrichter@gmail.com) > > Theory is knowledge that doesn't work. Practice is when everything works > > and you don't know why. (Hermann Hesse) > > > > > -- Michael T. Richter (GoogleTalk: ttmrichter@gmail.com) It's OK to figure out murder mysteries, but you shouldn't need to figure out code. You should be able to read it. (Steve McConnell) --=-DN/6/TBkz7AAneaRIhEA--