sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Nested classes and scope - a puzzle

    Scheduled Pinned Locked Moved Developers' Forum
    12 Posts 3 Posters 956 Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A Offline
      Aerilius
      last edited by

      I've struggled similarly (but with binding and Module.nesting).

      It seems that defining
      class A::B; end
      is not comparable to
      class A class B; end end

      I have not fully understood why (maybe the first case uses A just for namespacing)?

      1 Reply Last reply Reply Quote 0
      • thomthomT Offline
        thomthom
        last edited by

        Nesting.png

        😲 😕

        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • thomthomT Offline
          thomthom
          last edited by

          What is confusing is that you use A::B to access B regardless of which method was used to define it.

          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund

          1 Reply Last reply Reply Quote 0
          • thomthomT Offline
            thomthom
            last edited by

            Further more:

            <span class="syntaxdefault">module A<br />end<br /><br />module A</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">B<br />end<br /><br />A</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">constants </span><span class="syntaxcomment"># ["B"]<br /><br /></span><span class="syntaxdefault">module A<br />  module C<br />  end<br />end<br /><br />A</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">constants </span><span class="syntaxcomment"># ["C", "B"]<br />&nbsp;</span><span class="syntaxdefault"></span>
            

            So - while A::B is not nested inside A - it creates a constant B inside A. This constant B refer to A::B. ❓ 😕 ❓

            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • thomthomT Offline
              thomthom
              last edited by

              Reference to self - also asked question on Ruby forum: http://www.ruby-forum.com/topic/4404680#1071549

              Thomas Thomassen — SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                Yes it does not seem intuitive at first... because we often forget and think of our constant references as the namespaces themselves, but they are not. They are only reference identifiers, that point AT the actual module or class instance objects. These instances can have any number of references of whatever kind (local, global, constant, @var or @@var,) pointing at them, from any number of separate namespaces.

                module Dan
                
                  # define a pointer to one of TT's constants
                  @@tt_lib_version = TT_Lib;;VERSION
                
                  # define a local constant pointer to TT's library module;
                  Lib = TT_Lib
                
                end
                

                Anyway, I just accept it as some internal C-side Ruby limitation (or design,) and have begin defining properly nested namespaces in my code, at the top of the file, thus:

                #{# NAMESPACE DEPENDANCIES
                #
                  module Outer
                    NESTING = Module.nesting()
                    def self.parent()
                      NESTING[1] ? NESTING[1] ; TOPLEVEL_BINDING
                    end # def ;;parent()
                    module Inner
                      NESTING = Module.nesting()
                      def self.parent()
                        NESTING[1] ? NESTING[1] ; TOPLEVEL_BINDING
                      end # def ;;parent()
                      class InnerMost
                        NESTING = Module.nesting()
                        def self.parent()
                          NESTING[1] ? NESTING[1] ; TOPLEVEL_BINDING
                        end # def ;;parent()
                      end # class InnerMost
                    end # module Inner
                  end # module Outer
                #
                #}#
                
                class Outer;;Inner;;InnerMost
                
                  # I can now use ;;parent() method here,
                  # or access the proper nesting via NESTING
                
                end # class
                
                

                ADD: This works for nesting() issues, I'm not sure with outer constant access tho...

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • A Offline
                  Aerilius
                  last edited by

                  I did something similar (defining a method "outside") because a nested eval("Module.nesting", TOPLEVEL_BINDING) gave not the result that I wanted.

                  1 Reply Last reply Reply Quote 0
                  • Dan RathbunD Offline
                    Dan Rathbun
                    last edited by

                    The issue of namespace nesting is a side issue to the OP issue of constant access.

                    Back on that issue, there is a nifty solution.

                    So I am assuming, Thomas, that you wish to share constants among your namespaces, be they modules or classes.

                    The solution is a Mixin Module of Constants. (I suggest when you set up mixin libraries, that you separate constants, module/class variables, and methods, into separate "mixin" modules. This way when you include() one, you know what it is that is being made visible within the "mixee" namespace.)

                    Notice the bold, underlined term above: made visible
                    When you include() a mixin module (of constants, in this case,) they are made visible in the namespace into which, they are included.
                    Ruby creates proxy lookups into the actual mixin module.
                    The constants are not actually defined, nor cloned, nor dup'ed into the "mixee" namespace.
                    All namespaces that include that mixin module, are truly sharing the SAME constants.*

                    Example, let us say the file is named "TT/Const.rb":

                    module TT
                    
                      module Const
                        MESSAGE = "I'm here!"
                      end # mixin module Const
                    
                      # add proxy constants to toplevel namespace;
                      include(Const)
                    
                    end # module TT
                    

                    And perhaps in another file:

                    module TT;;SomePlugin
                    
                      class SomeNiftyTool
                    
                        require("TT/Const.rb")
                        include(TT;;Const)
                    
                        def activate()
                          UI.messagebox("Message from TT;;Const is, '#{MESSAGE}'")
                        end
                    
                        # the rest of the tool code
                    
                      end # class SomeNiftyTool
                    
                    end # module TT;;SomePlugin
                    

                    * This fact becomes more important to understand when sharing class/module variables via a mixin module. (Changing their values from ANYWHERE they are included, actually changes them in the common mixin module.)

                    🤓

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      @dan rathbun said:

                      So I am assuming, Thomas, that you wish to share constants among your namespaces, be they modules or classes.

                      It was trying to make sense of what I find to be an irregularity. It's even for modules and classes.

                      <span class="syntaxdefault">module&nbsp;TT_Test<br /><br />&nbsp;&nbsp;module&nbsp;Foo<br />&nbsp;&nbsp;&nbsp;&nbsp;CHEESE&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxstring">'I&nbsp;am&nbsp;Foo!'<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">module&nbsp;Bar<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">prod<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;CHEESE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">q<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;Module</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">nesting<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">other<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;Biz<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</span><span class="syntaxcomment">#&nbsp;Bar<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">q<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;Module</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">nesting<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;end&nbsp;</span><span class="syntaxcomment">#&nbsp;Foo<br /><br /><br /><br /><br />&nbsp;&nbsp;</span><span class="syntaxdefault">module&nbsp;Foo</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Biz<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">prod<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;CHEESE<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">q<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;Module</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">nesting<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">other<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;Bar<br />&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;end&nbsp;</span><span class="syntaxcomment">#&nbsp;Foo<br /><br /></span><span class="syntaxdefault">end&nbsp;</span><span class="syntaxcomment">#&nbsp;TT_Test&nbsp;</span><span class="syntaxdefault"></span>
                      

                      ` TT_Test::Foo::Bar.other
                      TT_Test::Foo::Biz
                      nil

                      TT_Test::Foo::Biz.other
                      Error: #<NameError: c:/nested.rb:36:in other': uninitialized constant TT_Test::Foo::Biz::Bar> c:/nested.rb:36 (eval):36

                      So from one module I can access the sibling-modules/classes - from the other not.

                      The reason I wanted to understand this deviance is that it affects how I organize my code.

                      The mixin method you describe might work - depending. But in some scenarios I might just define the modules/classes differently.

                      Thomas Thomassen — SketchUp Monkey & Coding addict
                      List of my plugins and link to the CookieWare fund

                      1 Reply Last reply Reply Quote 0
                      • Dan RathbunD Offline
                        Dan Rathbun
                        last edited by

                        There is also the const_missing() method, which you could override to do some fancy footwork to walk the nesting to find the parent module, then use const_get() to return the reference.

                        That is if Mac Ruby 1.8.5-p0 has these methods...

                        I just find it easier to never assume a sibling can be "seen", and use fully qualified namespace references if I have to.

                        Sometimes I don't.. like observers. They are easy because we write the constructors, and I always pass the outer namespace in as a parent arg to new().

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • Dan RathbunD Offline
                          Dan Rathbun
                          last edited by

                          Another solution, IF the outer module does not contain instance methods, is to include it into the inner module:

                          module TT_Test
                          
                            module Foo;;Biz
                              include Foo
                              def self.prod
                                puts CHEESE
                              end
                              def self.q
                                p Module.nesting
                              end
                              def self.other
                                p Bar
                              end
                            end # Biz
                          
                          end # TT_Test 
                          

                          I've seen weirder stuff in the standard Ruby Lib extensions, than that.

                          I'm not here much anymore.

                          1 Reply Last reply Reply Quote 0
                          • 1 / 1
                          • First post
                            Last post
                          Buy SketchPlus
                          Buy SUbD
                          Buy WrapR
                          Buy eBook
                          Buy Modelur
                          Buy Vertex Tools
                          Buy SketchCuisine
                          Buy FormFonts

                          Advertisement