Readability and writability (syntax)
Memory management
Performance of generated code
Size of generated code
Support for (enabling of) incremental development environments
Debuggability
Dylan was designed to be both easy to write and easy to read and understand. The syntax resembles a less verbose Pascal, but still easy for programmers unfamiliar with Dylan to understand the code. For example:
if (foo > 3 & foo < 5)
Conclusion: Dylan's syntax is very readable and maintainable.
print(transcript, foo is in range);
end if;
Dylan, like Smalltalk, allocates objects in the heap. While more expensive than stack allocation (as is commonly done with C++), heap allocation eliminates the possibility that an object may become deallocated while some client retains a pointer to the object. However, Dylan's use of type declarations and the avoidance of pointer arithmetic allows a Dylan compiler to allocate objects on the stack or inside variables if the compiler can determine that its safe to do so. The straightforward semantics of Dylan makes this kind of optimization tractable. As Dylan compiler technology improves, we should be able to realize similar storage efficiency to C++, but do so in a safer and more flexible way.
Of course, automatic memory management substantially improves code quality by eliminating the 30-50% of C++ instructions concerned with memory management. This is, it not only deletes statements and destructors, but awkward designs necessary to cope with the need to explicitly delete everything at exactly the right time and place.
Conclusion: Dylan's memory management is better than any of the competition.
Dylan is capable of producing very fast code. Although it is more flexible than C++, it is purposely less flexible than Smalltalk. As with C++, the development environment can be separated from the Dylan program under development, so that the compiler can assume that only certain well-defined sorts of changes can occur to a completed Dylan application. In particular, Dylan supports dynamically-linked libraries, which can add subclasses and new polymorphic methods. The Dylan language allows the programmer to specify which classes and which generic functions can be extended in this way. Only those will retain flexibility at the expense of speed. The compiler will optimize away the flexibility of everything else in the Dylan program.
The straightforward semantics of Dylan allows the compiler to determine the appropriate degree of flexibility at every function call, producing tighter code than C++. Changes to the program, e.g. adding or removing classes and polymorphism, potentially affect the compilation of all the code in the program. The automatic program-wide optimization by the compiler eliminates the need for the programmer to reoptimize the details of her program whenever large changes occur.
Conclusion: A production Dylan compiler can produce code whose performance is comparable to well-written C++, but without the manual optimization performed by C++ programmers.
The Dylan language has been designed to minimize the number of required run-time facilities, relegating anything that is useful but not really necessary to separate, optional libraries. The functions and classes required by the language are necessary and sufficient to ensure a high degree of compatibility between separately-developed modules. C++s lack of any standard libraries is a serious impediment to reusing code.
The module and library system in the Dylan language has been designed to support separate compilation and dynamically-linked libraries. The use of shared dynamically linked libraries (DLLs) for the basic run-time library and the application framework, as is common in Windows programs, results in distributable applications that are much smaller than comparable C++ applications that use an application framework. Dylan benefits from much of the research into Lisp compilers. Techniques such as CPS conversion can be used to produce code that is highly optimized, with such features as tail-recursion removal, closure optimization, and lifetime analysis. This results in generated code that is comparable in size to that generated by mainstream C++ compilers.
Objective-C programs are similar to C++ programs, with the exception that Objective-Cs large class library is similar to Smalltalk's or Dylan's. Objective-C has been used primarily on UNIX, where shared libraries arent an issue for the user. Since Objective-C uses a traditional text-file-based compiler, and not Smalltalk's environmental approach, its generated applications are considered ordinary in size.
One of the surprising results from C++ is the large amount of space taken up by the virtual function tables. It is not uncommon to see 20-30% of a compiled C++ program consist of just these tables. Both Smalltalk and Dylan use a dynamically optimizing dispatch system to minimize this space without impacting performance significantly.
Conclusion: Dylan is suitable for producing standard, shrink-wrapped applications, with deployed size on a par with C++ and Objective-C, and much better than Smalltalk.
Dylan programming follows the traditional source-text-editing model, but has been designed for incremental development by running the macro system at the parse-tree level. This allows the dependency web within a Dylan program to be easily calculated and maintained. In addition the polymorphic dispatch mechanism uses dynamic linkages, resulting in a minimal need for recompilation whenever even major changes, such as changing the layout of a class, occur.
Conclusion: Dylan has the best balance between practicality and incrementality, giving turn-around times measured in seconds, but with high efficiency code.
Dynamic languages support the best debuggers. The run-time safety and the flexible linkages within dynamic languages allow the programmer to modify running programs by adding or modifying functions, classes, and variables. In Smalltalk, writing a program and debugging it are completely interwoven, and use the same tools.
Dynamic languages are flexible, yet safe at run-time because all objects are tagged in memory with their type. This allows dynamic linkages to be checked for correctness as the program runs, eliminating the crashes and memory corruption that frequently results from the use of the equivalent void* declaration in C and C++. This early error trapping is invaluable for finding the precise cause of bugs, rather then attempting to deduce the cause of memory corruption in a C++ program, where the bug and the program crash are logically unconnected.
Dylan has much in common with Smalltalk, in that the program state is obvious to the debugger and the programmer. While Dylan has fewer dynamic linkages than other dynamic languages, an incremental compilation system for Dylan can still make patches to running programs by maintaining a complete dependency network, recompiling and reloading all affected definitions when the programmer makes a change.
This combination of run-time type information and incremental recompilation allows a Dylan development system to clearly debug and safely update optimized code in a running application.
Conclusion: Dylan provides the high visibility and control for which Smalltalk is prized, but without sacrificing optimization.