2.35. Koenig Lookup

Consider the following example:
Start felix section to tut/tutorial/tut-1.35-0.flx[1 /1 ]
     1: #line 3724 "./lpsrc/flx_tutorial.pak"
     2: //Check lookup:koenig
     3: //Check lookup:dependent
     4: #import <flx.flxh>
     5: 
     6: module A {
     7:   struct X {
     8:     x: int;
     9:   }
    10: }
    11: val e = A::X(5);
    12: print e.x; endl;
End felix section to tut/tutorial/tut-1.35-0.flx[1]
Start data section to tut/tutorial/tut-1.35-0.expect[1 /1 ]
     1: 5
End data section to tut/tutorial/tut-1.35-0.expect[1]
There is a subtle point here in this code. (Isn't there always?) Recall that
  e.x
is transformed by desugaring to the function application
  get_x e
If that is so, how is it that the get_x of (A::X) is found, when it is not visible in the top level scope? The answer is that I told a white lie before.

What really happens is that e.x is transformed into a method application. This is exactly the same as a function application, except that overloading uses a special kind of lookup for the method name, called Koenig Lookup, after its inventor, Andrew Koenig.

Koenig lookup works by searching the module in which the type of the expression e is defined: in Felix the type must be generative, which means it must be a declared type such as a named struct or union and not an implicitly defined type like a tuple, pointer, or function type (typedefs do not count here, as in C they just specify an alias, they don't define a type).

In the example, 'get_x' is defined in the module X, because A is defined in the module X, and since e has type 'A', Felix looks in module X for 'get_x'.

Koenig lookup only works for method calls, that is, when you use the syntax e.x.