8.12

4.9 Class Namespaces🔗ℹ

A name defined by class works as a namespace to access field selectors and methods of the class. It also works like the namespace form, because the body of a class can include export forms to export additional bindings. Other definitions can also be written in the class body, and those definitions are accessible outside the class only if they are exported.

class Posn(x, y):

  fun get_origin():

    Posn(0, 0)

  export:

    get_origin

> Posn.get_origin()

Posn(0, 0)

There’s a subtlety, however, when definitions within the class body try to refer to the class. Unless the reference is sufficiently nested, it can’t work, because the class is not defined until all of the class body forms are processed.

> class Posn(x, y):

    def origin = Posn(0, 0)

    export:

      origin

Posn: undefined;

 cannot reference an identifier before its definition

One way around this problem is to not put the definition inside the class, but still export it from the class. Just like in namespace, an export form in class can export any binding that is visible in the environment, including things defined outside the class form.

class Posn(x, y):

  export:

    origin

def origin = Posn(0, 0)

> Posn.origin

Posn(0, 0)

> Posn.x(Posn.origin)

0

> Posn.origin.x

0

Another solution is to use class.together, as described in the next section, but putting helper definitions after the class can avoid a small amount of overhead for instance checks.