![]() |
gbeta is a programming language in the Scandinavian tradition starting with Simula, initially created as a deep generalization of the language BETA. It supports a fully general version of family polymorphism, as well as propagating combination of classes and methods (also known as deep mixin composition), and many other powerful language mechanisms. You can download a compiler and execution environment for gbeta, and the source code of this implementation is freely available under the GPL license.
![]() |
The language gbeta emphasizes orthogonality and generality in the sense that it offers few, but powerful language mechanisms, which may in turn be combined freely. In particular, it enables defined entities such as classes and methods to be extended and refined by filling in placeholders as defined by the language or indicated by keywords. At this point we will describe some of these mechanisms briefly; the details may be looked up elsewhere on this website, e.g., in the tutorial.
Starting with a very well-known incarnation of this principle, one
type of open placeholder is the list of declarations of features in a
class. Using this extension feature simply means adding new
declarations in a subclass, e.g., such that a ColorPoint
class can have a getColor feature in addition to the
features of its superclass Point. It is of course
possible to do exactly the same thing in essentially every
object-oriented language today, but in gbeta it is just one out of
several modes of extension, and they are not all equally mainstream.
One type of open placeholder in gbeta which is less well-known is
concerned with a list of statements in the body of a method. By
default, extra statements can be added at the end of such a list,
which means that a method in a subclass will do what the superclass
does, and then proceed to execute additional statements specific to
the subclass. An explicit keyword, INNER, may be used to
indicate that an arbitrary location in the method body should be used
as the open placeholder rather than the end of the method. Note that
this means that the behavior of a method in a subclass is an
extension of the behavior of the method in the superclass,
rather than a replacement. It is as if the code in a method
is accumulated when traversing the inheritance path from the place
where the method is first declared down to the run-time class of the
object whose behavior is being considered, and then every inheritance
level gets the opportunity to "fill in the blank" with its method
body, where "the blank" is the (single or multiple) occurrence of
INNER, or the end of the method if no INNER
is present.
An old controversy lies herein. In fact, it takes some time to get used to the idea that methods should not override other methods, they should refine them by adding new behavior to the placeholder locations. This philosophy is strictly enforced in BETA, but in gbeta it is possible to force a replacement (as in a standard override semantics of method redefinitions), by means of the flexible support for mixin composition and even reordering in gbeta. Nevertheless, the fundamental structure of the language emphasizes extensions and refinements, and it is indeed possible to achieve a style of programming where this structure is put to good use. Other parts of the language design help in this respect, because they enable flexible management of definitions whereby the need to override (i.e., regret and undo) inherited behavior may be avoided in almost all cases, because the amount of boilerplate code it takes to request a certain (default) behavior exactly where it is needed is much smaller than in most other languages. As you may already have guessed, this language is non-standard in a number of ways, and it may be necessary to rethink some programming habits in order to get "into" this kind of programming.
A third type of open placeholder is an inner class. Such a class may be declared as a feature of its enclosing object, and it may be refined (to a subclass) in a subclass of the enclosing class. This mechanism is commonly known as a virtual class, and gbeta supports a very general notion of virtual classes where a refinement declaration (traditionally known as a further-binding of the virtual class) may refine that class by means of a mixin-based combination process that recursively propagates into the block structure. In other words, a virtual further-binding may change that virtual class to a subclass containing virtual classes which are themselves further-bound to subclasses of their previous values, and so on.
Finally, gbeta unifies classes, methods, and many other language
constructs into a single abstraction mechanism, the pattern.
This means that everything said about methods above applies to
classes as well, and vice versa. So, for instance, the recursively
propagating combination process mentioned above applies to methods
inside classes, and classes inside methods, and classes inside classes
inside classes, and all other nesting sequences, because they are
technically just patterns all of them, and only their intended style
of use makes it natural to prefer the word "class" when talking about
some of the patterns and "method" when talking about others. An
"object" is just an instance of a pattern which is kept around for a
while because its state and identity is useful, whereas a "method
invocation" is an instance of a pattern which is useful primarily
because of its side-effects on the enclosing object or its returned
results. In any case, it is a property of objects that they may have
a declared communication interface (traditionally known as the
enter- and exit-list), and this may be used
as the argument list and returned-results list of the "method
invocation" if the object is being used as a method invocation, or it
may be interpreted as a user-defined assignment/evaluation semantics
for the logical state of the object, if it is used as a traditional
"object".
The gbeta language is statically typed, and the core of the type system has been proven sound (NB: the literature about such things is listed on the papers page, but the text of this website does not in general include literature references, because it is oriented towards practical use of the language and tools). The type system is special in that it deals with run-time values; in particular, types depend on their enclosing objects such that "the same type" inside two distinct objects are in fact distinct types. Inclusion of run-time values into the type domain is commonly known as dependent types, and in this case they are quite simple because they are only concerned with object identity. A type is considered to be inside an object in the same sense as an instance of a Java inner class is considered to be inside an enclosing object. This is known as family polymorphism, and another terminology which specifically puts the focus on the value dependency is path-dependent types, which was coined by Martin Odersky when he introduced a variant of this kind of types in the language Scala. Together with propagating combination this enables higher-order hierarchies, which is the ability to use inheritance to create extensions and variants of entire inheritance hierarchies rather than single classes.
Inheritance in gbeta is based on mixin composition, which is again
governed by a linearization algorithm. A class is (conceptually,
though not necessarily in the implementation) just a list of mixins.
A type, however, is a set of mixins, because the ordering is
irrelevant from the typing point of view. Being a subtype is the same
as being a superset in terms of mixins, and this means that the
subtype hierarchy is the full lattice of all the possible sets of
mixins, connected by subtype edges according to whether or not there
is this superset relation among their mixins. In other words, gbeta
subtyping is structural with mixins as the basic granularity. It is
nominal with respect to individual declarations, because I found
it natural to associate a group of declarations in a declaration block
(which is just a brace-enclosed block, {..}) with a
certain interpretation or contract, such that we do not mess up the
draw method which means "put some pixels on the screen"
with the draw method which means "get ready to shoot
somebody". We do not care, however, exactly which inheritance (or
class combination) expressions were used to provide us with one or the
other of those draw methods (or both, indeed, because
they may actually co-exist in the same object and still be both
individually callable and dynamically dispatched).
A special concept in gbeta is that of an invisible mixin. An invisible mixin is a mixin that contains only private declarations, which may also be additions of invisible mixins to nested classes or methods. The point is that the presence or absence of an invisible mixin in a class makes no difference for the accessible features of its instances, or the accessible features of instances obtained indirectly, e.g., as the returned result from a method. Hence, invisible mixins may be added or even removed from classes or objects without affecting their type properties. Typically, invisible mixins are used to express the implementation layer of a class.
In gbeta, object metamorphosis coexists with strict, static type-checking: It is possible to take an existing object and modify its structure such that it becomes an instance of a given class, which is possibly only known or even constructed at run-time. In general, the new class of the object must be a subtype of the old class of the object, such that it never gets a smaller set of defined features (which could lead to a message-not-understood error at run-time). Hence, the static analysis ensures run-time type safety, even in such a dynamic scenario as that of objects changing their class.
It is possible to define relations between virtual classes, e.g., to
specify that the class MyPoint must be a subclass of
YourPoint (without committing to exactly what classes they
are). This makes it possible to define a kind of constraint graph
of classes. It ensures that certain relations hold, such that
one inheritance operation may give rise to a complex but orderly
propagation of type changes in a framework of classes. These
inter-virtual-class subtype constraints are not a new mechanism in the
language, they are just the natural explanation of the effect of using
one virtual class as the superclass of another one.
Moreover, gbeta supports inheritance hierarchies not only for
classes but also for methods. This can be used together with dynamic
inheritance to build dynamic control structures; dynamic
control structures enable your algorithms to be parameterized with
e.g. a while statement, an iteration through all elements of a given
list, or reading input from a file. Note that a control structure as
a parameter is richer than a procedure or function parameter, because
the control structure can provide a name space to its body, just like a
built-in .
There are many other features in gbeta which are innovative compared with the mainstream, and some of them are discussed in the pages of this website. As mentioned, the scientific literature discusses the things mentioned above in more detail, but this website does not include literature references at the level expected in a research paper because of its orientation towards practical programming. Please consult the papers mentioned in papers for a more detailed treatment.
The language gbeta was originally created in order to try out the language design space around the language BETA, i.e., to try out different design choices than the ones which have been made in BETA, and in particular to generalize the basic concepts. To this day, gbeta shares a number of fundamental properties with BETA, so if you have knowledge about BETA, or even BETA programming experience, it will be usable in an indirect manner in a gbeta context. For instance, the radical unification and the pattern concept were invented for BETA, but they have been deeply generalized in gbeta. Moreover, the gbeta syntax has a similar structure as the BETA syntax, but it probably takes a careful analysis of the very different looks of actual programs to see how much they have in common. For instance, arguments passed to a method and results returned are declared in very different locations in a BETA and a gbeta method declaration, but it is still the case that both are capable of declaring a list (tuple) of results to return, and both use a recursive semantics for argument and return specifications that enable abstraction (which means that argument list structures and types may be reused as a named abstraction rather than by copy-paste operations on actual lists of declared names).
Already BETA has strong support for co-evolution of classes,
expressed as mutually dependent virtual patterns.
For example, the classes Vehicle and
Operator might depend on each other, and they should
"know" each other's enhancement to Car respectively
Driver. The support for class co-evolution is even
more powerful and flexible in the generalized language gbeta,
because of its support for general, mixin-based, propagating class
combination, where BETA is restricted to strict, static
single-inheritance. In this way, and in many other ways, BETA
experience may give hints about what gbeta can do, but it may also
lead to some confusion because of the generalizations and lifted
restrictions in gbeta compared to BETA.
![]() |
There is currently no support for calling external code, such as C
or Java libraries, and this prevents the direct use of standard
libraries from various other sources. The virtual machine is special
to gbeta, so there is no JVM or CLR or similar well-known platform
running underneath, either. Another limitation is in program size. It
would cost too much memory and take too long to run e.g. a 100,000
line program (using many libraries pushes the effective line-count
up); up to 3000 lines is more realistic. The current gbeta
implementation is more for the (academic) geek who is interested in
programming language design and type systems, and less for the
no-nonsense practical programmer who wants to write large
mission-critical applications. In other words, it's slow but it uses a
lot of memory. ;-)
![]() |
is always welcome, about the language and/or its implementation, about the language design effort that it incarnates, and about this web site.
![]() |
...the funny symbol on the many colored background is the gbeta logo, a stylized version of the letters "gb". You are welcome to use this logo on your own web pages if you want to refer to gbeta. And here is a picture which shows a situation during a gbeta session hosted in GNU Emacs (click on it to see more):