Predictions. Hmmm. Okay.
We will start to abandon our pathetic attempts to understand the complexity of the systems we're targeting, and the complexity of interaction of the fine-scale structuring of data in our standard libraries (much less our user-defined code) with those systems.
We will allow judgements we now consider "simple", but which profilers show we often get wrong, to be made by the profilers in the first place. Actual testing and profiling information will drive compilation and interpretation, allowing standard libraries to choose among many possible implementations of the results we specify.
New programming languages, accordingly, will need to specify less of specific methods and more of desired results and performance requirements. When and as they do specify specific methods, they will do so behind a "choice point," where there are many possible implementations to choose from and the system is required to make an automated choice.
I predict that infrastructure for testing programs will get incrementally better. I predict that profilers and profile-awareness will get built into (some) development tools at a more fundamental level. This will allow profiling information (from earlier runs, from earlier versions, from earlier in the same run, or even possibly from live performance testing of prospective code snippets during compilation) to drive many of the tradeoffs and representation decisions made when interpreting the code or preparing it for execution.
These systems will produce code optimized for any specific architecture even though the developers of the systems do not understand in detail the specifics of all those architectures. Instead, the tools will automatically create profiles by testing the performance of benchmarks on the target architecture, and optimize according to those profiles.
This has been made more valuable both by the increasing ubiquity of virtualization and by the increasing complexity and variety of CPU architectures; the compiler can no longer assume that the code it is generating will run on a particular hardware or OS, nor on any particular implementation of an instruction set or the target virtual machine. Compiler writers can no longer be expected to apply detailed human understanding to all of the increasingly diverse and increasingly complex systems on offer, let alone how those systems will interact with particular implementations of the code that their programmers write.
The ability to optimize for the system, processor type, or VM that is actually there now and the way it actually performs, as opposed to the system, processor, or VM someone expected to see or the performance they expected that inevitably-different system to have when and where the development tools were written, has become more valuable than ever.
I also expect that in some experimental languages software development systems will be making simple representation decisions that we now consider to be of algorithmic importance for us. Human expectations of the performance of a given data structure are often wrong in the first place, subject to our ignorance of the specific cache line lengths, parallelism capabilities, memory latency, or task-switching overhead of the processor in question. In subsequent uses of our code, when code is reused in another project, these structuring decisions can *become* wrong with no change in the code, simply due to changed usage patterns. In subsequent deployments of the code where it is run on a different OS, processor, or VM implementation, or when code is prepared for execution on a different processor type with different capabilites (CPU, FPGA, GPU, DSP, etc) structure choices can again become wrong due to different underlying capabilities making some operations more and less expensive, again when the code has not changed.
Therefore the software development systems should "correct" these decisions to reflect actual use -- which amounts to wiping out the distinctions among the fine-scale structure decisions that can be "corrected" in the first place. And therefore we need a way to specify algorithms as vaguely as possible (don't worry, we'll call it "abstraction" instead of "vagueness"), both to cater to our pathetic human understanding of how our code actually runs on the machine, and to allow the tools maximum latitude in deciding how best to achieve the results our code specifies given the current computing substrate.
Therefore I predict a continuing increase in algorithmic and structural abstraction, with a concomitant continuing loss of specificity in the details of data structures. We will reach a point when we won't be able to tell, even by tracing our definitions all the way down to the limits of what our languages can express, whether something is implemented in terms of pointers or in terms of indexing; that kind of transitive beta-reduction on definitions will be able to tell us only that those were among the choices from which a profiler-driven decision was made.
In seven years, there will be at least a few emerging languages embracing this strategy, in which "collections" make pretty much every possible operation available in the programming environment, and then it's left to the compiler or runtime environment to decide whether a particular collection is best represented as linked list, or an array, or a doubly linked list, or a heap, or an associative array or a hash table or how it's indexed, or as a database tuple, or whatever, making a decision based on what representation best optimizes runtime, storage, and responsiveness rather than because the programmer told it specifically how to represent a given collection.
Replacing the loss of specificity in data structures, we will see two new kinds of information encoded in computer programs, and likely abstracted to have scopes that tell what specific subparts of code they apply to, the same way variables and constants and procedure names have scopes that tell where they are visible. First, programmers will optionally write code specifying decision parameters, to inform the system of what performance characteristics are considered desirable in making decisions about representation and how to optimize.
Second, programmers will encode optional information which the system might or might not be able to prove, both for the system's benefit in making optimization decisions and for their own in assessing the code's correctness, knowing at the earliest possible instant when and where it has gone wrong. This includes the kind of information that we now regard as type information, for example that numbers need be represented only to a given level of precision or within a given range, in order to get the intent of the code right. But this information will not be (correctly) seen as specifying a particular binary format. Instead it will specify minimum requirements that *restrict* the choice of binary representations used, permitting but not requiring greater range or precision.
It also includes a kind of information now included in a much broader notion of types not shared by most programmers, which we mostly now regard as programming invariants, constraints, security requirements, or contracts. These are crosscutting concerns that we currently usually implement by means of painstaking individual assertions in many places. For example, a programmer might be able to state (once!) that, within a particular scope, an arbitrary boolean expression will NEVER become true, and rely on the development system to test the expression any time it touches any of the variables of that expression and immediately halt the program and display the current values of those variables if it ever does become true.
We're going to see more languages with "selectable safety levels" where the programmer can optionally add type declarations to address undecidables, and the development environment can be commanded to do anything from "RUN IT AND CRASH IF YOU HIT A TYPE ERROR" all the way up to "EITHER PROVE THIS ENTIRE PROGRAM TYPE-CORRECT, OR TELL ME WHAT YOU CAN'T DECIDE."
Some of them will support even more esoteric commands, such as "EITHER PROVE THIS PROGRAM WILL HALT, OR TELL ME WHY IT DEFINITELY WON'T, OR TELL ME WHAT YOU PROVED YOU CAN'T DECIDE, OR TELL ME WHAT YOU WERE TRYING TO PROVE WHEN YOU RAN OUT OF TIME."
None of this will be mainstream within seven years. But I expect that we'll see (indeed, in some cases, we are already seeing) its beginnings.
Ray Dillinger