In its current state, Nickle is a quite useful tool. A number of enhancements to Nickle are planned to increase that usefulness, by making Nickle easier to use and harder to make mistakes in.
First and foremost, while Nickle's current full static type system is a marked improvement over dynamic typing alone, it is not the end of the road. Explicitly stating the types of names is tedious and error-prone, which may partially explain the lack of strong static typing in most recent scripting language designs. There are two possible improvements over explicit static typing which might be adapted to Nickle with good effect.
Parametric polymorphism, as found in ML and Generic Java (GJ) [BOSW98] (and its close conceptual cousin type templates, as found in C++) tries to capture the idea that an expression that is independent of the details of its input and output types should not be tied to those details. Parametric polymorphism avoids much ``copy-and-paste'' coding while still retaining the benefits of full static typing. For example, linked list code which is independent of the type of list elements need not be repeated for each possible structure type, a savings in code size and in the potential for error. Since polymorphic typing is fully safe if properly designed and implemented, the downside is minimal: a slight decrease in the expressiveness of the language due to extra constraints on the code.
ML goes a step further, and adds automatic static type inference to the language. Instead of having to explicitly declare all types, undeclared types are inferred from context, and the resulting type assignments are checked for consistency. Experience has shown that polymorphic type inference has much of the flexibility of dynamic typing while still retaining most of the safety of static typing. For a language like Nickle which is to be used as a calculator and for algorithmic prototyping, this seems like an especially ideal combination.
The Nickle implementation is currently several times slower than equivalent C code. This is ameliorated somewhat by the fact that its primitive operations on numbers are well-tuned and exceptionally fast, and by the ability to implement much more sophisticated algorithms in Nickle in equivalent time and code. Nonetheless, there are applications where better performance would be desirable. The obvious approaches of optimization of byte code or compilation to native code and optimization thereof should be explored. There is no reason in principle why Nickle programs should be dramatically slower than C programs, although there is some overhead inherent in the language.
An interesting tack in this direction would be to produce a Nickle compiler to byte code for the Java Virtual Machine (JVM). Running Nickle code under the JVM would bring a couple of important advantages. First, portability to non-UNIX environments would be greatly enhanced. Second, significant performance improvements might be available ``for free''2 as a result of the JVM runtime native-code compilation and dynamic code optimization commonly available in many implementations. On the downside, the mismatch between Java's object-oriented model and Nickle's imperative-functional model might make things difficult, and the filesystem-based module system of the typical JVM implementation is ill-suited to Nickle's requirement for separating files from namespaces.
It would be nice if Nickle supported a wider range of built-in types, constants, and operators. The limited range of numeric types is particularly problematic: obvious candidates include the natural numbers, finite fields (particularly ), and various extensions of the reals, particularly complex numbers. Better semantics and more powerful operators for dealing with vectors, matrices and tensors would also be a plus.
The natural numbers have been in and out of the language at various times in its history. They are currently out, to simplify the language, but they are being reconsidered since their inclusion would close the one known hole in the static type system of the language.3C-style 32-bit integers were supported at one time, but were deemed to be too much of a special case to expose to the user. Consideration is currently being given to adding general finite field constructors and operators, but there are notable complications.
The lack of complex numbers is slightly embarrassing, but ideas about regularizing them and implementing them in a sane and compatible way have so far been hard to come by. Issues such as the representation of complex coefficients are vexing: for instance, are complex integers desirable? In addition, it is not totally obvious that the complex numbers should be preferred to other extensions of the reals, yet including multiple generalizations makes it difficult to find a suitable static type lattice and correspondingly to choose runtime promotions.
In addition to numeric types, Nickle could arguably use a larger range of modern structured datatypes, such as lists, sets, and curried functions. There are several reasons why we have not provided these to date. Notably, until a polymorphic type system is implemented, static typing issues are difficult to resolve reasonably. In addition, it is problematic to provide a built-in implementation of datatypes which might be sensibly implemented in multiple ways having different properties. Sets are a particularly good example of this: Pascal's bitsets have very different runtime properties from sets of integers represented as search tries, and both representations are difficult to generalize to sets of values, such as structures, which have no natural inherent ordering. It is questionable whether the language should make choices for the user about representation issues, and so far it has been shied away from.
While Nickle's supporting libraries are already well along, further work needs to be done here. The floating-point math support needs to be validated and extended: it would be especially nice to make it compliant with the rounding and precision rules of the IEEE floating point arithmetic standards [IEE85,IEE87]. The string support is extremely rudimentary. Built-in support for array slicing, array comprehensions, and similar features would occasionally be useful. Some implementations of standard Abstract Data Types (ADTs) such as priority queues might occasionally ease algorithm development.
Support for built-in operators on vectors and arrays of numbers would be a real plus, and has no obvious downside except a slight increase in language complexity. The main reason for their lack of current inclusion is the lack of a need for them in the authors' work.
It would be nice to add some sort of support for workspaces or the like to Nickle, to aid scratch-pad calculation. A save command would be a good start, but in principle Nickle could allow capturing a true continuation and saving it to a file, which would lead to a nice implementation of both workspaces and checkpointing.