Assumptions

RobertFischer edited this page Sep 13, 2010 · 11 revisions

Every programming language has assumptions. Every programming language takes certain programming problems to be normal and certain other programming problems to be beyond the pale. Java assumes that you don’t need to do low-level hardware interface, and bit-twiddling will be minimal. It also assumes that it’s okay to make microsecond pauses: real-time guaranties aren’t something Java programming will give you.

These assumptions are the key power of high-level languages. By making assumptions, we make space for optimizations. We give the language leverage over our programming issues. DSLs and convention-based development frameworks have taught us this lesson most clearly—by assuming that all programming is a select number of tasks, we can put user-developers into truly powerful environments. While Ashlar doesn’t go as far as DSLs and convention-based development frameworks, it certainly makes some strong assumptions so that it can make some strong optimizations.

Here are the assumptions for Ashlar. If these assumptions don’t hold for your project, then Ashlar is not the language for you.

Most Programming is Decision Logic and I/O

Most programming consists of sucking in data from one location, transforming it, making decisions about what to do with it, and then dumping it into another location. This describes web services/apps, file processing, and EDI. It probably describes whatever your last paying gig was. So that is what we are optimizing for: decision logic and I/O.

This specifically means we are not optimizing for numerical analysis. We are not optimizing for real-time systems. Problem spaces that we are targeting are graphs/networks, data transformations, and project logic.

Surprising Bugs are Humiliating

Built into many languages are tricky, obnoxious issues that crop in in bad ways and unlikely places. The NullPointerException is a key example. The fact that 0.7 + 0.1 == 0.8 may or may not be true is another classic (and see other arithmetic issues). These kinds of issues have traditionally been a reality that programming languages forced us to deal with: built into C-derivative languages has been ugly surprises which surface as intermittent and surprising bugs. These bugs as miserable, and need to be driven out of the language: the language should not surprise the programmer.

Classpath Issues are Infuriating

When a developer builds code, they know what libraries it takes to run that code. The code is then compiled, and in most languages, that information is lost. When the compiled code is shared, the person receiving the code then has to go figure out how to get their libraries all lined up right so that it executes. This time—the time spent by the user recovering the information the developer knew—is utterly wasted. Worse, if things are even slightly awry, explosions are difficult to debug. Classpath issues should be an implementation detail of the language.

Code Should Be Readable

The goal of code is to communicate intent to both a human being and a computer. The game of designing a programming language is striking the balance between the human-abstract approach to language and the computer-absolute approach to language. In general, the readability sensibilities of Ashlar lie more with the high-level minimalism of OCaml and Ruby than with the low-level keyword and symbol mash of Java and C++. In part, this means that Ashlar will chose readability of simplicity over the flexibility and choice of exposed implementation details.

Error Messages Should Be Meaningful

The difference between a workable library and a great library is in the error messages. People have to learn our language, they have to learn our library, and so they will make mistakes. Even great developers make mistakes. The job of the language should be to expose the reason for the error in the clearest way possible. Developer time should be spent solving the problem, not figuring out the problem in the first place. (And yes, NullPointerException, you are exemplar of failed error messages.)

We Execute in a Multithreaded and Distributed Environment

The era of single-threaded code is over. Code needs to be multithreaded, and the developer should not be the one hand-rolling the multithreading. Like JoCaml, Ashlar takes responsibility for implementing the multithreading and leaves the programmer with the job of noting the points where breaks in the threading should occur.

It would be even nicer if Ashlar could take responsibility for the distribution of distributed execution.

Sometimes We Want to Code in a Natural Language

Ashlar is a good language, but since every language is born into a reality of assumptions and trade-offs, there will be tasks where other languages are better suited. Scala has their XML literals, which are digging at this space. Instead of tightly integrating with a particular language, however, Ashlar should make it easy to drop into other languages in general.

The Basic Unit of Executable Code is the Jar

Any non-trivial class has no meaning without its context. An individual class is like an individual word: it simply hints at meaning and a larger structure without any coherence in itself. Therefore, the jar—the module or component—is the basic building block of an application, and not the class.

Start-Up Time Does Not Matter (Much)

Headius once lamented the fact that a Java-based ls is impossible: the start-up time is just too bad for the JVM. JVM start-up time is made worse by the prevalence of frameworks like Spring and OSGi that want to eat a bunch of time to do up-front configuration. The more configurable the language and program, the more up-front configuration checking needs to be done, which means more file system queries. All of this adds up to atrocious start-up time behavior.

So let’s not fight that. Let’s accept that the language is not going to be used for system utilities or short-running programs, but will be used by long-running applications for whom start-up time is a piddling detail. We don’t want to make start-up time an epic pain, but efforts to optimize for start-up time are tangential to the purpose of the language.

Memory Usage Does Not Matter (Much)

Java applications regularly run with gigabytes of memory at their disposal, so why worry about a language’s memory footprint? While we don’t want to become a memory hog and an undue burden on the host machine, given the choice between saving memory and a better user experience, we’ll take the user experience. Ashlar embraces good waste as a core principle.