Introduction to Avail
Avail is a multi-paradigmatic general purpose programming language whose feature set emphasizes support for articulate programming.
Traditional programming languages provide only small context-free grammars and low-level values. They are therefore well suited for solving software engineering problems, like sorting an array of 32-bit integral values in place, but poorly suited for solving problems of other kinds. This is unfortunate, because the overwhelming majority of programs target some other domain. The vocabulary and concepts of bits, bytes, loops, arrays, and floating point numbers are extremely poorly suited for tackling everyday problems in chemistry, banking, insurance, pharmacology, linguistics, and a thousand other fields.
It is, of course, possible to describe a thing at the wrong level and using the wrong language. Consider the following example, written in C, one of the most successful programming languages of all time:
But there are many career programmers who would rather say:
Programmers must continually solve adaptation problems in order to translate high-level concepts from the rich vocabulary of a natural language and the specialized jargon of a problem domain into the impoverished expression space of a traditional programming language. Many everyday problems are hard enough to describe and solve using humanity's best tools for communication: natural language and visual metaphor. Any programmer who has ever worked on a nontrivial problem does not need to imagine the difficulty of encoding a good solution using only low-level concepts and a handful of special keywords; she does this very thing for a living! Even using best practice in software engineering, throughout her career she will solve the same adaptation problems repeatedly, gradually building up a repertoire of design patterns, mental boilerplate, dirty tricks, and professional discipline in order to compensate for the chronic deficiencies of traditional programming languages. Nevertheless, any complex project spends its early years replete with bugs that arise directly from the mismatch of the problem and solution domains.
Obviously, a natural language pidgin is not always the right language for the job. If you have ever read mathematical proofs from the era before modern mathematical notation, then you know that natural language absolutely falls flat on its face in certain situations. Clearly there is no single language that is right for every job. What good is your own natural language when confronted with someone who doesn't speak it? But there is always some language that is right. This is why Avail strives to provide the tools needed to build any language whatsoever. Avail is not so much a language, as an infinite collection of languages, waiting just beneath the surface.
Articulate Programming with AvailArticulate programming endeavors to streamline software development by reducing the degree of mismatch between the problem and solution domains.
In the articulate programming paradigm, a programmer undertakes a project by developing a domain-appropriate lexicon and phraseology which are leveraged directly to implement a solution that is readily accessible to domain experts and software experts alike. Articulate programming is nothing more, and nothing less, than using the right language and conceptual framework for the job.
It is obvious that a programming language should support articulate programming, so why don't traditional programming languages do so? Because articulate programming depends upon harmony among a multitude of features not simultaneously present in any traditional programming language.
Avail is the pioneer of articulate programming. Its numerous features cooperate for a singular purpose: to enable a programmer to talk about her objects of interest using the best language for the domain of her problem. In no particular order, Avail's feature set includes at least:
- A modular, dynamic, unrestricted grammar supported by an efficient compiler that concurrently explores all possible parses in pursuit of a semantically unambiguous interpretation.
- An infinite algebraic type lattice that confers a distinct type upon every distinct value.
- Intrinsic support for a rich collection of immutable types, including tuples, sets, maps, functions, and continuations.
- A static type system capable of leveraging every feature of the type lattice.
- Efficient multiple dispatch for all named operations.
- Automatic memory management capable of coalescing equivalent immutable values.
- A concurrency model that features lightweight threads multiplexed onto a pool of native threads and managed by a time-slicing, priority-driven preemptive scheduler.
- Lock elision for accesses of values that are visible only to a single lightweight thread.
- Fully asynchronous I/O: no Avail thread is ever blocked waiting for an I/O event.
- Reified immutable continuations that support resumable exceptions, computational backtracking, and general coroutines.
- A module system that supports hierarchical encapsulation and method renaming.
- Separation of source code and object code.
- A universal serialization framework that supports even functions, continuations, and lightweight threads.
- Sincere and model-complete introspective facilities.
- A mechanism for observing expressions rather than values, thereby enabling a novel method of efficient, transactional change propagation that is more natural and powerful than the observer pattern or functional reactive programming.
- An optimizing dynamic translator that supports type inference, function inlining, and de-optimization.
- Bidirectional foreign function interface to Java.