Possibilities and challenges¶
In this lesson we shall consider possible directions for future developments in computer programming language, research challenges whose solution could enable novel software technologies, and the kinds of new AI-based applications that we may expect to see.
Obviously it is not easy to predict the future, so this lesson gives only a personal idea of what may be the significant developments in programming. However, the lesson mentions a wide range of possibilities and it is likely that some of these will turn out to be very important in the future of programming.
Learning outcomes
After completing this lesson you will be able to describe and give an overview of possible future developments in:
- programming languages
- software related research areas
- novel computing applications.
The future of programming¶
The nature of programming has changed rapidly over the past 50 years. Changes have mainly followed directions that relate to key features that have been found to increase ease of programming and reliability. These primarily come under the following headings:
- conceptual abstraction from low level details
- modularisation of program components
- increasing attention to data and data structures
- promulgation of non-algorithmic aspects of code.
Abstraction¶
Abstraction in the way we program has come a long way since the original programs that were coded directly in the machine instructions that are processed by the CPU devices of computers. Here are a couple of ideas of how abstraction could be taken even further.
Virtualisation and cloud computing¶
Modern computing is dominated by distributed services for which information storage and computational resources are provided by the cloud and cloud computing resources.
Virtualisation is the process of creating a virtual version of something. You may think that virtualisation involves an abstraction away from physical implementation details. This is true from a hardware perspective: a specific physical computational device has been replaced by a program or collection of programs, which has the same computational functionality as the physical computer.
However, from a programming point of view, virtualisation is almost the opposite of abstraction. In writing a program to run on a virtual machine in the cloud we write code as if it is running on conventional hardware (for example, we load and save files in the same way as we would when they are stored on our local hard drive).
These files may only exist within the memory of a remote machine or the file content could be distributed between different segments of memory (or disk on many different machines). So how would we abstract away from physical implementation details from a programming point of view?
Abstraction from physical implementation details¶
Traditional programming languages are built upon a conception of programming that is tightly bound to the particular physical objects and mechanisms that support the information processing capability of computers. This is why we normally think of data in terms of storage devices (ROM and RAM), files, records, text strings, etc.; and we consider computation in terms in terms of complex procedures for manipulating symbols by means of a specific predetermined sequence of steps.
However, when we consider computational processing purely in terms of information and possible transformations we may apply to it, the particular details of storage are irrelevant. Whether information is stored in a file, or in memory in the form of some data structure, the transformations or extractions that may be applied to it are essentially the same (though of course it is usually faster to transform data in memory than on disc, and to keep data safe it is wise to store it on disc, rather that in memory).
In fact, modern computer architectures already blur the differences between, say, a file and a data structure stored in memory. As mentioned above, what may appear to a programmer as a file often exists only in memory as part of the data structure used to represent a virtual machine. And conversely, what appears to be a data structure may actually be stored on disk (as when swap space is used).
In the future, programming languages may treat data storage in a much more abstract and general way. Instead of writing code instructions to save data to a file, we would simply specify that the data should be stored in a persistent way, so it would still be available after our program had finished, and perhaps also that it should be made available to other programs (e.g. via a URI). Instead of loading data from a file into memory, we would just declare that we want rapid access to a certain data object (which again might be specified by a URI).
Abstraction from specific names of program elements and components¶
From the point of view of computer program execution the specific names of variables, functions, classes, modules, packages, files etc. are arbitrary. They just provide means of establishing a connection between a place in a program where a certain symbol string (for example, a variable name) is used and some location in memory or on disc where the the referent information object is stored.
To produce reliable and adaptable computer programs, you should abstract away from specific details to produce a more general solution. However, in assigning names to functions, classes and files, we associate specific sequences of symbols to refer to these objects. With small programs this is not usually a problem. However, as systems become larger, languages incorporate more and more built-in functions and large numbers of modules and packages are available for use, a programmer has to be aware of of a huge number of different names for both functional components and data objects.
In recent years there has been a massive growth in online documentation, and systems that organise and maintain this in a semi-automatic way have been developed (for example, websites such as docs.python.org).
But it can be difficult to find what you are looking for unless you already know its name. For instance how would you know that a function that would be useful for you is in a package called
pandas
or numpy
or cv2
, unless you already know the names of those packages and the kinds of functionality they support?
Ideally we would like to access program elements by means of a general method of organisation, not just by using specific names. It is currently unclear how this would be achieved. However, the idea of program semantics, and the more established ideas regarding data semantics may provide a basis by which we can organise program elements primarily in terms of their meaning, rather than the names that programmers give to them.
Program semantics¶
Semantics is the study of meaning and how we can describe and classify meanings. Originally, programming languages were treated as primarily syntactic objects, that is sequences of symbols. However, those symbols do have a meaning in terms of what happens when they are executed. As programming languages have developed into much more structured forms, categorisations of data types and components such as functions, classes, methods, modules, packages etc. bring out semantic structures and relationships among program elements. It is likely that this kind of structuring will be further developed so that more aspects of the meanings of functions and classes will be made explicit. This may enable the organisation of programs to be more comprehensible, and provide a way to reduce the problem of dealing large numbers of disorganised names of program components that was highlighted in the previous section.
Declarative coding¶
In various previous lessons declarative programming languages were mentioned. The main advantage of a declarative approach is that it can improve intelligibility. It can be regarded as a form of abstraction in that the declarative parts of a program need not specify how that declared information is to be used, and the parts of the program that use the declared information, do so in a general way that does not depend on the specific details of the data. This can be a very powerful way of programming and is likely to become more prevalent.
Knowledge-based programming¶
Moving further into the future, it may be that rather than coding algorithms (or specific declarative information) to solve a specific problem, you could represent knowledge in a general way that could be flexibly applied to solve a variety of problems. So instead of coding a program to implement particular functions, you would create a knowledge base. The knowledge base could could then be used for a variety of purposes, by means of a wide range of queries or requests that can be answered or obeyed by the system.
In fact this kind of functionality already exists in some forms. For example when we use a Web search engine such as Google search, we are using the Web as a knowledge base and getting information back that is related to our query. However, this kind of querying does not use genuine knowledge about the content of the Web; the search engine mainly just matches words in the query with words in documents on the web (though actually more and more semantic information is being used by Google to control the way their search engine works).
Another way in which much more fully fledged knowledge-based programming can be implemented is by using a logic programming language such as Prolog (e.g. SWI Prolog). A Prolog program can act as a knowledge base and can answer queries by means of logical inference, so largely fulfils the aspiration of knowledge-based programming. However, representing large amounts of knowledge in Prolog involves several difficulties:
- coding knowledge in a comprehensive and consistent way is a large and intricate task
- Prolog programming is often error prone, unless the programmer has a sound grasp of how the language works
- debugging can be difficult
- query answering can be very inefficient unless the code has been very carefully designed
- and efficiency can vary greatly according to the particular types of query that the program is given to evaluate.
Modularity¶
As has been emphasised in several lessons of earlier units, modularity is a key concept in programming, which greatly facilitates the construction of large reliable systems. Modularity is also closely associated with encapsulation and with portability. In recent years the most significant development connected to these attributes is probably containerisation.
Containerisation¶
The idea of a container and containerisation has become very significant recently, especially in relation to cloud computing. (Note that in Python the word 'container' is used to mean a type of object that can contain other object. Here we are talking about something different.) The two best known container technologies at the moment are Singularity and Docker. The Docker website defines the concept of a container as follows:
"A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings." (from docker.com)
Probably the main reason to use containers is for portability. Code that depends on being run with a particular operating system system set-up because it makes use of a variety of other software components within that system can be packaged up into a single container unit, which can be transported to another system and will still run. The Docker documentation describes their containers as 'lightweight' but a docker image could easily be more than 1GB in size, so not exactly featherweight. However, 1GB is probably a lot smaller than the size of the whole file system that we would use to crate the software (which could be hundreds of GB).
Containers can also be regarded as providing a form of encapsulation and they can also be used as modular units within larger systems. For instance the Kubernetes system provides a mechanism for orchestrating software services that involve multiple containerised applications.
Data and data structures¶
Recall the quote from Linus Torvalds that we saw way back in Unit 2, in the lesson on the Significance of Data in Computation:
"I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships."
(Linus Torvalds, 2006-08-28, Message to Git mailing list)
Hopefully the content of this module has demonstrated good reasons to believe that Linus is largely right (though I would say that there are also situations where good programmers will worry about algorithms). We can expect that data and data structures will always play a significant role in programming; and, as long as programmers seek to develop new kinds of software, they will also create new forms of data structure. New kinds of data will require new data structures for their representation and new algorithms will make use of new data structures in their implementation.
Data semantics and ontologies¶
One type of data that is increasingly seen as important is meta data, or in other words data that specifies information about data. As systems deal with data that is more and more diverse and is integrated from many sources there is a need to keep track of what data means and where it comes from. The field of Semantic Technology deals with methods for representing and manipulating information about the meaning of data and for using this information to support various kinds of application. There are two kinds of situation in which this is useful (often these occur together):
-
You have complex data of many types and want to develop an application that can make use of interconnections between different data types.
For example, we may want to write software for managing a website and business procedure for a company selling many different kinds of products to a variety of customers. Both the products and customers may have many attributes and we need to ensure that complex conditions are satisfied to match customer requirements to product features. -
You need to combine data from several different sources.
For example we may want to integrate environmental data from many different countries to carry out a global analysis of some environmental conditions.
Precise specification of the semantics of a vocabulary of conceptual terms can be represented by means of logical languages. A specification of this kind is known as an ontology. Various representations have been developed for computational representation of semantic information, such as RDF and OWL as well as tools for editing ontologies such as Protege and mechanisms for querying data that is associated with an ontology specification, such as SPARQL.
Data driven programming¶
In many of the preceding lessons of this module we have seen that data can play a significant role in programming, not only in being an input that programs operate upon to produce output, but also in supporting and shaping the functionality that programs deliver. As we have seen, the field of Data Science is continually developing new ways to extract information from data and Machine Learning explores ways to use data to achieve functionality that we would be unable to accomplish by direct programming.
For a very interesting exploration of the possibilities opened up by using data a a driving force for computer applications you are recommended to watch the following video of a lecture by Peter Norvig (who is a co-author of the leading AI textbook Artificial Intelligence: A Modern Approach and a director of research at Google:
Promulgative programming¶
To promulgate an idea is to make it widely known by communicating it to anyone for whom it may be relevant. Traditionally, programming has focussed on constructing functions that produce some output from some input or
starting state. However, many other auxiliary programming related features and tools have arisen that are more about communicating the status, purpose and usage of code rather than defining the actual code functionality. Such
features range from those directly related to an algorithm's function, such as exception handling (e.g. Python's try
and except
), self verification (assert
) and execution timing functions,
to features related to usage and maintenance, such as automatic documentation (e.g. via docstrings),
API specifications and version control (git
), as well as including more socially oriented features relating to programming communities (github
, Kaggle
)
and program distribution (pip
, conda
).
Such features have proved to be very useful and are increasingly popular. However, they form a very disparate collection of coding conventions and tools that each require separate investigation and investment of effort by programmers before they can make use of them. It is likely that promulgation will become increasingly recognised as a key aspect of programming, and general frameworks for unifying different promulgation mechanisms will be designed. I predict that in the future full-blown promulgation languages will be developed and will operate as wrappers around conventional code components. These will support a wide range of meta functionalities relating to code development and usage. Ultimately it may be possible to create programs purely by promulgating specifications, requests and even payment offers, for required functionality: the actual algorithmic code would then be obtained automatically from remote sources. Conversely, programmers who are interested in supplying or writing algorithms could promulgate details of what they can provide and be automatically paid for fulfilling requirements of other system developers.
Question
Why is there no Wikipedia page on promulgative programming ?
Answer
The term promulgative programming does not exist. Brandon made up the word promulgative. Judge for yourself whether it is a useful concept.
All programming language features begin with general ideas about what might be useful for creating programs. These can eventually evolve into specific commands and code structures.
Can you think of an idea of you own that might be a useful feature in a programming language of the future?
Automatic coding and program synthesis¶
Now we look at a possibility that may put programmers out of a job.
The past was once the future; so, to form a view of the future, it may be revealing to survey the past. There is no more entertaining way to gain insight into the early development and popularisation of computing than by flicking though magazines such as InfoWorld. In the issue from May 25, 1981 on pages 1, 7 and 60 you will see references to The Last One, a new software product produced by a British company called D.J. "AI" Systems, which is described on page 1 as "one of the most significant software products ever created". Judging from its very brief Wikipedia article, The Last One did not quite live up to its hype. Nevertheless, the idea behind it was interesting, and seemed to have great potential. The goal of The Last one is described as "to give the computer all the low-level chores involved in coding and debugging programs, thus leaving to people only the general design of the software".
The idea that code could be created automatically (or at least-semi automatically) is certainly attractive. One can imagine that this would lead to much quicker program development, perhaps more reliable programs, and could possibly enable one to develop software that would be too complex for human coders to develop without some automated help.
Automated coding can actually take many forms, ranging from simple autocompletion of variable and function names to fully automatic creation of a program from a natural language description, or from a set of sample inputs and outputs. The general aim of automatic programming has actually led to several different research fields being explored, including the following:
The prospects for automatic programming are uncertain. Some take the view that it is impractical or even impossible because of the many technical challenges it presents; and that more traditional programming ideas, such as modularisation and abstraction, provide a more realistic route to achieving quicker, more reliable and more advanced software development.
Self modifying code¶
Closely related to automatic coding, is the idea that a computer program could modify its own code. This is not allowed by the
Von Neumann Architecture, which keeps programs and data separate, but is possible with nearly all modern computers, in which the same
memory is used to store programs and the data operated on by programs (thus they can potentially change their code in much the same way that they operate on data). In Python is easy to write code that modifies itself (for example,
by creating strings representing function definitions and executing them using the eval
command). The problem is that it is very difficult to do this in a way that would not cause unpredictable behaviour and program
crashes.
Many types of program do in fact modify their code in a limited way. An example of this is genetic algorithms, and most other ML algorithms that use training or reinforcement can be regarded as self modifying. However, these types of algorithms have a main control system that is not modified. I believe that there are no examples of programs that can modify any part of their own code that have been successful in achieving useful functionality.
Some have suggested that AI systems can become super-intelligent by modifying their own code. We will consider this possibility later in this Unit in the lesson on Dangers of AI.
Research challenges and opportunities¶
Clearly there are many difficult problems that will need to be overcome for the development of new software capabilities and novel applications. Here we shall just look at a few that seem particularly significant and challenging.
Natural language understanding¶
The problem of natural language understanding is generally regarded as AI-complete, meaning that solving it is equivalent to the problem of creating Artificial General Intelligence (i.e. Strong AI). That language is central to intelligence, especially in the view of those advocating symbolic approaches to AI, was discussed in Unit 5, in the lesson on Approaches to AI. And informally, we can argue that, if an artificial agent is capable of holding an intelligent conversation, it must be intelligent. This is the basis upon which the Turing Test and also underlies the idea of the Winograd Schema Challenge which involves the correct interpretation of certain kinds of sentence known as Winograd Schemas.
During the early development of AI, natural language processing problems were mainly approached using symbolic AI techniques such as parsing algorithms and knowledge representation languages. However, more recently the problem has increasingly been tackled using ML techniques. Over the past few years, models based on ANNs trained on very large corpora of text data, have been developed, which can, with a high degree of accuracy, perform language processing tasks that seem to require some level of understanding. Most prominent among these is the BERT language model. More information about BERT can be found in the articles at devopedia.org and Google AI Blog and the original paper (of Devlin et al.) presenting the BERT architecture.
The problem of natural language understanding will no doubt be a major subject of AI research for many years to come. It seems unlikely that it will be fully solved in the near future; however, it is very likely that its study will lead to the development of many new programming ideas both in terms of algorithms and information representation.
Multi-scale reactive planning¶
Suppose I wake up and realise that I need to go to the university to deliver a lecture. In order to do this I need to formulate and carry out some kind of plan. This will involve a sequence of high-level goals that I will need to achieve in order to successfully give the lecture:
I need to get dressed, have some breakfast, check the time and place of the lecture, find and pack my laptop, choose a suitable mode of transport (walk, bike, bus?) and route, ..., set up my laptop, turn on the projection equipment. Finally, I am ready to give the lecture.
But each of these high-level tasks also involves a large number of smaller steps that need to be planned and successfully executed. Making breakfast involves opening cupboards and packets and operating kitchen equipment. Eating involves careful coordinated movements and manipulations, otherwise I will cause a lot of mess. Also, in order to get everything done in time, I may need to do some tasks in parallel, such as packing my bag while the kettle is boiling. To complicate things further still, not all plans may work out as intended: maybe my laptop is not on the desk where I expected it to be; I have to look round the flat and finally locate it on the sofa.
Although AI planning systems can compute quite long action sequences to achieve goals, the scenario described in the previous paragraph presents a planning problem that is far more complex than any modern AI planning algorithm would have any chance of solving. Humans, somehow seem to be able to split up planning problems naturally into different tasks and levels of granularity, so that our decision making at any one point in our activity is quite focussed despite there being a huge degree of potential interaction between different goals (somehow I forget about my laptop while making breakfast even though spilling tea on it could make it impossible to give my lecture). And we also seem to be able to adapt minor parts of our plans quite easily when things turn out a bit different from what was expected.
Tackling this kind of problem has been regarded as a key problem for AI since its beginnings (see papers such as Planning and Acting, Knowledge Strata: reactive planning with a multi-level architecture) and Touring Machines) and various general approaches have been developed in the fields of Hierarchical Planning (also know as hierarchical task networks) and Reactive Planning. However, in terms of the performance on figuring out plans for realistic real world planning scenarios, current AI algorithms do not come anywhere close to human capabilities.
Automated reasoning¶
The possibility of using automated logical reasoning in AI systems dates back to very early ideas such as John McCarthy's Situation Calculus (for the original proposal of the calculus see this classic paper). Unfortunately, automated reasoning using logical representations and inference is extremely computationally expensive. What is more, for many logical languages, testing inference can be undecidable, meaning that there can be no algorithm that is guaranteed to terminate in all cases. Nevertheless, the expressive power of logical language to represent a wide range of different kinds of information and the fact that inferences can derived automatically mean that automated reasoning is very attractive as a mechanism to be used within an AI system.
At one time (around the 80s) artificial neural nets (which were overviewed in the lesson on Approaches to AI in Unit 5) were considered to be a promising approach to develop AI systems. But they went out of fashion when it seemed that it was not possible to achieve useful functionality using this approach, at least not with the computing power that was available at that time. But of course with the computing power that is now available it has been found that extremely impressive functionality can be achieved from ANN-based systems.
The field of Automated Reasoning could be in a similar situation. Although research in this area has continued from the earliest days of AI to the present day, in recent years it has been considered by many to be an implausible route to achieving significant AI capabilities. This has been due both to the computational power required and also to problems in representing the knowledge required to support reasoning. Since computing power has continued to increase and there is much scope for further development knowledge representation methods (including by combining with ML techniques), it is likely that there will be significant future developments in automated reasoning, which could make it a powerful component of AI systems.
Synergies between symbolic AI and ML¶
As mentioned in the lesson on Approaches to AI in Unit 5, there is often scepticism from researchers in one of these areas to work following the other approach. However, it is increasingly recognised that there are many ways in which GOFAI and ML can be combined to develop advanced software capabilities.
In fact systems such as AI game playing agents often use search algorithms that are guided by heuristic functions that have been discovered by ML techniques. Symbolic KR can provide powerful reasoning capabilities, but these are limited both by the difficulty of acquiring the knowledge required to support the reasoning and the problem guiding the reasoning process towards making the desired inferences. It is possible that both these issues could be addressed by utilising ML within a symbolic reasoning system.
It is likely that investigation of possible ways to combine Symbolic AI and ML would be a very active research area in the future.
Quantum computing¶
In theory quantum computing can implement certain algorithms much faster than is possible with conventional hardware. Quantum algorithms make use of the idea of superposition to combine multiple items of information within a single quantum state (a Qubit). This enables massive parallelism for certain types of algorithm which could potentially mean that an algorithm that is of exponential time complexity on conventional machines could require only polynomial time if implemented on a quantum computer (see Shor's algorithm, which can be used to crack cryptographic encoding).
IBM and Intel Google have all been investing heavily in quantum computing research and are aiming to produce commercial quantum computation products with the next decade; and the Finnish-based company IQM is the leading European developer of quantum computers.
It is possible that quantum computing could massively increase the power of computers over the coming decades. However this is by no means certain. There are many technical issues that make construction and reliable operation of quantum computers extremely difficult. Furthermore, although quantum computing may reduce the complexity of a certain type of problems it is by no means clear that it gives significant advantage in solving the kinds of NP-hard search problem that are typically employed of Symbolic AI. (This article on The Limits of Quantum provides an accessible and entertaining exploration of this issue.)
Human Compatibility Issues¶
As computers become more and more closely integrated in to human life they affect us in many ways. They may change or replace our roles and affect our experience in our work, leisure and social interactions. It is clear that computers can provide significant benefits but they may also have negative affects on us. What I refer to as human compatibility issues covers all aspects of the interactions between humans and computers and potential problems that can occur. Addressing these issues will increasingly become a major topic of study in relation to technical design, and also to legal regulation and social policies. We shall cover issues concerning the most serious kinds of compatibility issue in more detail later in this unit, in the lesson on Dangers of AI.
Future Applications¶
We will finish the lesson by listing a range of directions in which significant developments and novel applications are likely in the near or medium range future. We will not go into details here, but you are but you are encouraged to investigate any that you are not aware of.
- autonomous robots
- worker robots
- driverless cars
- care and companionship
- human-computer interfaces
- voice controlled systems (more intelligent than Siri and Alexa)
- AI personal assistants
- ubiquitous AI
- blockchain technology
- computer enhancement of human abilities
- augmented reality
- powered exoskeletons
- cognitive enhancement
Question
Can you think of any significant types of future application that has been missed out of this list?
Exercise
Go through the above list of future applications and for each one write down a date for when you would expect that application to be available in a usable form for ordinary people to use. (E.g. in what year, if ever, would you expect to first travel in a driver-less car?)
You should write your estimates in your Personal_Log.ipynb
, notebook, and take another look at it in 10 or 20 years to see if your predictions were accurate.
Exercise
Select two or three of the types of future application listed above. For each of your choices identify research challenges that need to be addressed to achieve significant advances in developing that kind of application. Consider also whether particular types of program language innovation may be useful in order to develop the software required for that kind of application.
Lesson complete¶
You should now be able to understand the possible future developments in Programming languages, Software related research areas and Novel computing applications.
Select the next button to continue to the next lesson.