Language Reference/Basic Concepts/Scoping and Visibility


< Language Reference‎ | Basic Concepts

Revision as of 09:15, 4 July 2017 by Thomas Linder Puls (talk | contribs) (Visibility, Shadowing, and Qualification (example))

Name Categories

All names (identifiers) in Visual Prolog are syntactically divided into two major groups:

  • Constant names (starting with a lowercase letter)
  • Variable names (starting with an uppercase letter or an underscore)

Constant names (identifiers) are divided into the following categories:

  • Type names (i.e. domains and interfaces).
  • Domain carriers (i.e. classes and interfaces).
  • Names without parentheses (i.e. constants, fact variables of non-function type and nullary-functors).
  • Value returning names of arity N (i.e. functions, functors and fact-variables of function type).
  • Non-value-returning names of arity N (i.e. predicates, facts and fact variables of predicate type).

Visual Prolog demands that names do not conflict at the point of declaration, because then it would be impossible to solve the conflict at point of usage. Declarations can only conflict if they are in the same scope, because qualification with scope can be used to solve the conflict. A name in one category can never be in conflict with a name in another category, but as we shall see a single declaration might place a name in several categories.


The basic units of code organization accepted in Visual Prolog are packages. We use packages in Visual Prolog to organize and structuring things. The use of packages ensures homogeneity in structuring principles among different projects. Packages define the standard for tool structuring and ease sharing source code among projects.

The package is a collection of several grouped together interfaces and classes. The package provides some common name to all these interfaces and classes. Each declaration or implementation of each interface or class from a package is placed in a separate file. Each filename (of these files) coincides with the name of a class or an interface that is declared or implemented in this file. All package files are stored in the same separate package directory. (If a package contains sub-packages, then they are placed in subdirectories of the package directory.)

The concept of packages is used for grouping together several linked interfaces and classes. Packages can play a role of some class library. Packages can be used in your program instead of direct placing all used interfaces and classes into your program.

The accepted in Visual Prolog structure of packages and how packages should be included into projects are described in the VDE part of this help. (See Creating a Package in Creating New Project Items.)

Visibility, Shadowing, and Qualification

Most of the scoping rules are already mentioned above. This section will complete the picture.

An interface definition, a class declaration and a class implementation are scopes (scopes cannot be nested). An implementation (privately) extends the scope of the corresponding class declaration. The visibility is the same everywhere in a scope. This does especially mean that no matter where in a scope something is declared, it is visible in the whole scope.

Public names from supported interfaces and super-classes are directly (i.e. without qualification) available inside a scope, if it is unambiguous where they come from. It is illegal to use a name whose origin is ambiguous. All ambiguities in predicate calls can be removed by qualifying the predicate name with the class name (e.g. cc::p).

This qualification is also used to qualify calls of object member predicates of super-classes on the current object.

Visual Prolog has the following shadowing hierarchy:

  • Local
  • Super-class & opened scopes

Opened scopes have the same status as super-classes, so in the sequel we will just say super-classes.

The hierarchy means that a local declaration will shadow a super-class declaration. But there is no shadowing between super-classes; all super-classes have equal preference. If two or more super classes contain conflicting declarations then these declarations can only be accessed by means of qualification.

Example Assume the interface ixx and the classes aa and bb:
interface ixx
    p1 : ().
    p2 : ().
    p3 : ().
end interface ixx
class aa : ixx
end class aa
class bb
    p3 : ().
    p4 : ().
    p5 : ().
end class bb

The class aa creates objects of type ixx, whereas the class bb does not create objects at all.

In this context consider the implementation of a class cc:

implement cc inherits aa
    open bb
    p2(). % reimplementation of ixx::p2
    p5 : ().
    new() :-
        p1(), % aa::p1
        p2(), % cc::p2 (shadows aa::p2)
        aa::p2(), % aa::p2
        p3(), % Illegal ambiguous call: aa::p3 or bb::p3
        aa::p3(), % aa::p3
        bb::p3(), % bb::p3
        p4(), % bb::p4
        p5(). % cc::p5 (shadows bb::p5)
end implement cc
Since cc inherits aa all the predicates in the interface ixx are also visible in cc. Likewise the open bb qualification will make all predicates in bb visible in cc.