A brief summary of Sun's Fortress
j2xs' post about Sun Labs Programming Research Group's Fortress inspired me to dust off some writing I did back in graduate school. One of the questions asked by Dr. Greg Lavender of UTCS in our domain specific languages class was what new programming features Fortress (intentionally linked to an outdated version of the spec) contained and what facilities it had for "growing the language" (in the words of Steele). What follows is an adaptation of my response given nearly two years ago.
Fortress is intended to replace Fortran as a language for scientific computing. It is object-oriented, defining method interfaces through traits but allowing fields to be defined only at the level of the object. Objects are the leaf nodes in the acyclic trait hierarchy which, confusingly, is rooted at the trait Object. To my knowledge, this is a novel approach to class definitions. Traits may be parameterized on other traits, like generic types in Java, and also on operators, which Java does not support. Objects may also be parameterized but only on other objects.
Fortress allows top-level function declarations like C++, but unlike it allows multiple return values (this seems very convenient). It adopts the call-by-value calling convention like Java and C++, but allows Python-style keyword arguments in addition to positional arguments. The final positional parameter can be used to generate a function with an arbitrary number of arguments of that last type using a trailing ellipse. Fortress provides powerful assertion mechanisms for function definition such as requires, ensures (paired with provided), and invariant. These features will be very useful to programmers and limit the need to re-write assertion code with each project. Functions may be parameterized on traits, as well as other built-in types.
Fortress is imperative in the sense that it allows mutation and sequencing of statements, but unlike most imperative languages it enforces good programming practices by eliminating statements in favor of expressions (it reminds me a lot of Tiger from CS386L). I think the return value of assignment expressions is unclear from the specification; I assume it should be "()" as with loops, but an alternative would be the rhs value. Dispatch expressions seem to eliminate the need for allowing access to the type of objects and values, which could be a way of cleaning up standard OOP programming practices (like the use of instanceof in Java). Fortress provides a host of built-in aggregate data types and mechanisms for conveniently defining them (including aggregate expressions and comprehensions).
Fortress supports the creation of DSELs in a variety of ways. First, value objects allow the definition of primitive values. Fortress provides value objects that may be categorized into booleans, characters, strings, and numbers; an example extension is to define the number value object Complex and its associated operators. Allowing the definition of operators substantially improves Fortress' ability to support convenient syntax for DSELs. Fortress' most powerful support for DSELs comes in the form of syntax expanders. With the parametric expanders provided in fortress.syntax, any of Fortress' abstract syntax can be specified using its concrete syntax. This is very similar to the idea of macros in Scheme. The difference is the concrete and abstract syntax of Scheme are identical, both being composed of s-expressions. Fortress syntax expanders have all the power of Scheme macros, but lack their clarity.
Fortress seems to be a very rich language. I feel it bests both C++ and Java in terms of facilitating DSELs. It has the clean (but still somewhat verbose) syntax of Java and the ability to define operators of C++. Its object model limits the programmer to good style as in Java while allowing multiple inheritance as in C++. In addition, syntax expanders allow the language to grow in ways C++'s macros cannot approach. However, I am not convinced Fortress will be a better foundation for DSELs than a functional language like Scheme or Haskell. In both of these languages, any code you write seems to be a very natural extension of the provided base language. Fortress allows arbitrary specification of its abstract syntax, but in a way that does not feel as natural and simplistic. My argument here is merely about compactness of representation; Fortress' facilities for syntax expansion are no less powerful than that of most functional languages.




