-
-
Save Lichers0/070f3a1ece2b03f2eb91bff4e15dd15d to your computer and use it in GitHub Desktop.
Revisions
-
kyrylo revised this gist
Sep 2, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -125,7 +125,7 @@ A::B::C.class_eval do # A value of 42 for X. C is asked for X, it is not found, so # the calling scope(main/Object) is asked next. It is found # as Object::X and returns a value of 42. The lexical scope does # start at C but traverses into the calling scope and not the # definition of A::B::C. # assert X == 42 # => true -
kyrylo revised this gist
Sep 2, 2013 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -29,7 +29,7 @@ module A D = 5 module B module C # C is asked if its constant table has 'D'. It's not. # The next scope is B. it also does not have 'D' in its # constant table. The next scope is A. A::D is found and # the lookup stops. @@ -90,7 +90,7 @@ class A end end # A::C is asked if its constant table has 'X', It's not. # Next its superclass is asked: A::B. it does own the constant 'X' # and returns a value of 5. A lexical lookup(starting at A::C) would # have found 42(A::X).. -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -29,7 +29,7 @@ module A D = 5 module B module C # C is asked does its constant table have 'D'. it does not. # The next scope is B. it also does not have 'D' in its # constant table. The next scope is A. A::D is found and # the lookup stops. @@ -68,7 +68,7 @@ class A::B::C < D # D(the superclass of C), then its superclass(Object) is asked, # at which point a NameError is raised. # X # => 5 end ``` @@ -95,7 +95,7 @@ end # and returns a value of 5. A lexical lookup(starting at A::C) would # have found 42(A::X).. # assert A::C::X == 5 # => true ``` __LEXICAL LOOKUP AND CLASS/INSTANCE_EVAL__ @@ -128,7 +128,7 @@ A::B::C.class_eval do # starts at C but traverses into the calling scope and not the # definition of A::B::C. # assert X == 42 # => true end ``` -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -121,7 +121,7 @@ class A end A::B::C.class_eval do # A value of 42 for X. C is asked for X, it is not found, so # the calling scope(main/Object) is asked next. It is found # as Object::X and returns a value of 42. The lexical scope does -
Robert revised this gist
Sep 2, 2013 . No changes.There are no files selected for viewing
-
Robert revised this gist
Sep 2, 2013 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -139,6 +139,9 @@ contexts. You can follow the codepath much easier. To finish up an example of how those codepaths can be followed: ```ruby require "test/unit" include Test::Unit::Assertions class A class B # The lookup path for X (lexical lookup): -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -92,7 +92,8 @@ end # A::C is asked does its constant table have 'X', it does not. # Next its superclass is asked: A::B. it does own the constant 'X' # and returns a value of 5. A lexical lookup(starting at A::C) would # have found 42(A::X).. # assert A::C::X == 5 ``` -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 5 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -111,22 +111,21 @@ include Test::Unit::Assertions X = 42 class A X = 5 class B class C end end end C.class_eval do # A value of 42 for X. C is asked for X, it is not found, so # the calling scope(main/Object) is asked next. It is found # as Object::X and returns a value of 42. The lexical scope does # starts at C but traverses into the calling scope and not the # definition of A::B::C. # assert X == 42 end -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 7 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -110,12 +110,16 @@ require "test/unit" include Test::Unit::Assertions X = 42 class A X = 5 class B class C end end end C.class_eval do # A value of 42 for X. C is asked for X, it is not found, so -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -92,7 +92,7 @@ end # A::C is asked does its constant table have 'X', it does not. # Next its superclass is asked: A::B. it does own the constant 'X' # and returns a value of 5. A lexical lookup would have found 42. # assert A::C::X == 5 ``` -
Robert revised this gist
Sep 2, 2013 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,6 +22,9 @@ the ancestry tree. __LEXICAL LOOKUP__ ```ruby require "test/unit" include Test::Unit::Assertions module A D = 5 module B -
Robert created this gist
Sep 2, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,152 @@ Constant lookup in Ruby can happen lexically or through the ancestry tree of the receiver(a class or module). You can identify which lookup rules are being applied by the context you're in or by the syntax being used to define a class or module. A class body that is defined as `class A::B::C; …; end` will lookup constants through the ancestry tree when a constant is evaluated in its class body. Anytime you see `A::B::C` being used as syntax to define a class or lookup the value of a constant the ancestry tree is being used for the lookup. How would we apply lexical lookup in the definition of `A::B::C` if we know how to apply ancestry lookup? The syntax you use for the definition is what makes the difference. The first example defines a module with lexical constant lookup while the second example is defined to use the ancestry tree for lookup. The examples come with comments that explain what is happening and what it means for a constant to be looked up 'lexically' or through the ancestry tree. __LEXICAL LOOKUP__ ```ruby module A D = 5 module B module C # C is asked does its constant table have 'D'. it doe not. # The next scope is B. it also does not have 'D' in its # constant table. The next scope is A. A::D is found and # the lookup stops. # # the pattern to see here is that lookup is happening by # traversing back through the nested scopes. this is said # to be a lexical constant lookup. Anytime a class or module # body is defined like this constant lookup happens lexically. # assert D == 5 end end end ``` __ANCESTRY LOOKUP__ ```ruby class D X = 5 end class A::B::C < D # A constant lookup through the ancestry tree is implied # from the syntax we used to define the class. Anytime you # see the syntax A::B::C (in a class definition or expression) # you know constant lookup is going through the ancestry tree. # # C is asked does 'X' exist in its constant table, it does not. # Next the superclass of C is asked, which is D. D finds 'X' in # its constant table with a value of 5. # # neither B or A are asked for the constant like in a lexical # lookup. If X were not defined, C would be asked first, then # D(the superclass of C), then its superclass(Object) is asked, # at which point a NameError is raised. # X end ``` What about the `A::B::C` syntax to read the value of a constant? we know the lookup will go through the ancestry tree but lets take a closer look: ```ruby require "test/unit" include Test::Unit::Assertions class A X = 42 class B X = 5 end class C < B end end # A::C is asked does its constant table have 'X', it does not. # Next its superclass is asked: A::B. it does own the constant 'X' # and returns its value. A lexical lookup would have found 42. # assert A::C::X == 5 ``` __LEXICAL LOOKUP AND CLASS/INSTANCE_EVAL__ A class eval or instance eval will look for constants lexically. The difference about a lexical lookup in a class body definition and a block passed to class_eval is that class_eval will lookup from the calling scope and not the scope of 'self'(a Class or Module). An example(with comments) to illustrate: ```ruby require "test/unit" include Test::Unit::Assertions X = 42 class B X = 5 end class C < B end C.class_eval do # A value of 42 for X. C is asked for X, it is not found, so # the calling scope(main/Object) is asked next. It is found # as Object::X and returns a value of 42. The important # thing to note is that it was not found by going through # the ancestry tree of C. # assert X == 42 end ``` __FINISHING UP__ I think it is useful to know how constant lookup happens and in what contexts. You can follow the codepath much easier. To finish up an example of how those codepaths can be followed: ```ruby class A class B # The lookup path for X (lexical lookup): # C -> B -> A -> calling scope(main/Object). class C assert_raise(NameError) { X } end end end class A; end class D < A; end class A::B::C < D # The lookup path for X (ancestor lookup): # C -> D -> A -> Object assert_raise(NameError) { X } end ```