- Feature Name:
- Start Date:
- RFC PR: https://github.com/Whiley/RFCs/pull/13
- Tracking Issue: https://github.com/Whiley/WhileyCompiler/issues/842
This proposal is for a syntax change to fully-qualified names to something more familiar to systems programmers, and to clarify the meanings of different qualified names.
Currently, fully qualified naming in Whiley follows the syntax of Java. Specifically, we write things like this:
import std.ascii import std.io import println from std.io method main(ascii.string args): io.print("Hello ") println("World")
. operator is used to construct fully-qualified names of
xxx.yyy.zzz. The context in which these are used
determines their meaning. For example, in the context of an
statement the path
xxx.yyy.zzz identifies a module
std.ascii above). However, in the context of a function or
method invocation (e.g.
io.print() above) the path identifies a
symbol (i.e. a named declaration in some module, such as a
The goal of this proposal is two-fold. Firstly, to clarify the distinction between module names and symbol names. Secondly, to provide a syntax which is more familiar to systems programmers (e.g. from C++ or Rust backgrounds).
A qualified name is a sequence of identifiers separated by
std::ascii::to_string, etc). A qualified
module name is a qualified name where the last component identifies
the name and the preceding components (if any) constitute the
path. For example, in the module name
std::ascii it follows that
std is the path, and
ascii the name. A qualified symbol name is
a qualified name where the last component identifies the symbol and
the preceding components (if any) constitute a module name. For
example, in the symbol name
std::ascii::to_string it follows that
std::ascii is the module name, and
to_string the symbol name.
The above example in the proposed syntax would be:
import std::ascii import std::io import println from std::io method main(ascii::string args): io::print("Hello ") println("World")
NOTES: The separator
:: is used for module names over
avoid overloading this with the field access operator. Likewise,
is adopted because it is familiar to C++ and Rust programmers.
Furthermore, it does provide a useful syntactic spacing between
modules and names.
Qualified names can be used in a number of different contexts:
- Imports. When used in
importstatements, qualified names are always module names (e.g. in
import std::ascii, it follows that
std::asciiis a module name).
- Expressions. When used in expressions, qualified names are
always symbols names (e.g.
- Types. When used in a type, qualified names are always symbol
Another aspect of qualified naming is that a qualified name can be
fully-qualified or partially-qualified. For example,
the fully qualified name of the
io module. In contrast,
is a partially qualified name for the
io rather than
std::io). It follows from this that one can
choose to use fully qualified names to avoid
import statements. For
example, we could rewrite the above without
import statements as
method main(std::ascii::string args): std::io::print("Hello ") std::io::println("World")
In general, however, the use of fully-qualified names should be discouraged in favour of partially qualified names.
- Module name. Identifies a module within the system
- Symbol name. Identifies a named entity within a module. This
could be, for example, a
- Fully qualified name. A fully-qualified module name is the complete system path for that module. Likewise, a fully-qualified entity name employs a fully-qualified module name.
- Partially qualified name. A partially-qualified entity name uses an unqualified module name.
Drawbacks and Limitations
Obviously, existing code will be broken.