What Kind of a Thing Is the Wolfram Language?
I’ve sometimes found it a bit of a struggle to explain what the Wolfram Language really is. Yes, it’s a computer language—a programming language. And it does—in a uniquely productive way, I might add—what standard programming languages do. But that’s only a very small part of the story. And what I’ve finally come to realize is that one should actually think of the Wolfram Language as an entirely different—and new—kind of thing: what one can call a computational language.
So what is a computational language? It’s a language for expressing things in a computational way—and for capturing computational ways of thinking about things. It’s not just a language for telling computers what to do. It’s a language that both computers and humans can use to represent computational ways of thinking about things. It’s a language that puts into concrete form a computational view of everything. It’s a language that lets one use the computational paradigm as a framework for formulating and organizing one’s thoughts.
It’s only recently that I’ve begun to properly internalize just how broad the implications of having a computational language really are—even though, ironically, I’ve spent much of my life engaged precisely in the consuming task of building the world’s only large-scale computational language.
It helps me to think about a historical analog. Five hundred years ago, if people wanted to talk about mathematical ideas and operations, they basically had to use human natural language, essentially writing out everything in terms of words. But the invention of mathematical notation about 400 years ago (starting with +, ×, =, etc.) changed all that—and began to provide a systematic structure and framework for representing mathematical ideas.
The consequences were surprisingly dramatic. Because basically it was this development that made modern forms of mathematical thinking (like algebra and calculus) feasible—and that launched the mathematical way of thinking about the world as we know it, with all the science and technology that’s come from it.
Well, I think it’s a similar story with computational language. But now what’s happening is that we’re getting a systematic way to represent—and talk about—computational ideas, and the computational way of thinking about the world. With standard programming languages, we’ve had a way to talk about the low-level operation of computers. But with computational language, we now have a way to apply the computational paradigm directly to almost anything: we have a language and a notation for doing computational X, for basically any field “X” (from archaeology to zoology, and beyond).
There’ve been some “mathematical X” fields for a while, where typically the point is to formulate things in terms of traditional mathematical constructs (like equations), that can then “mechanically” be solved (at least, say, with Mathematica!). But a great realization of the past few decades has been that the computational paradigm is much broader: much more can be represented computationally than just mathematically.
Sometimes one’s dealing with very simple abstract programs (and, indeed, I’ve spent years exploring the science of the computational universe of such programs). But often one’s interested in operations and entities that relate to our direct experience of the world. But the crucial point here is that—as we’ve learned in building the Wolfram Language—it’s possible to represent such things in a computational way. In other words, it’s possible to have a computational language that can talk about the world—in computational terms.
And that’s what’s needed to really launch all those possible “computational X” fields.
What Is Computational Language Like?
Let’s say we want to talk about planets. In the Wolfram Language, planets are just symbolic entities:
✕
EntityList[EntityClass["Planet", All]] |
We can compute things about them (here, the mass of Jupiter divided by the mass of Earth):
✕
Entity["Planet", "Jupiter"]["Mass"]/Entity["Planet", "Earth"]["Mass"] |
Let’s make an image collage in which the mass of each planet determines how big it’s shown:
✕
ImageCollage[ EntityClass["Planet", All]["Mass"] -> EntityClass["Planet", All]["Image"]] |
To talk about the real world in computational terms, you have to be able to compute things about it. Like here, the Wolfram Language is computing the current position (as I write this) of the planet Mars:
✕
Entity["Planet", "Mars"][EntityProperty["Planet", "HelioCoordinates"]] |
And here it’s making a 3D plot of a table of its positions for each of the next 18 months from now:
✕
ListPointPlot3D[Table[ Entity["Planet", "Mars"][ Dated[EntityProperty["Planet", "HelioCoordinates"], Now + Quantity[n, "Months"]]], {n, 18}]] |
Let’s do another example. Take an image, and find the human faces in it:
✕
FacialFeatures[CloudGet["https://wolfr.am/DpadWvjE"], "Image"] |
As another example of computation-meets-the-real-world, we can make a histogram (say, in 5-year bins) of the estimated ages of people in the picture:
✕
Histogram[ FacialFeatures[CloudGet["https://wolfr.am/DpadWvjE"], "Age"], {5}] |
It’s amazing what ends up being computable. Here are rasterized images of each letter of the Greek alphabet distributed in “visual feature space”:
✕
FeatureSpacePlot[Rasterize /@ Alphabet["Greek"]] |
Yes, it is (I think) impressive what the Wolfram Language can do. But what’s more important here is to see how it lets one specify what to do. Because this is where computational language is at work—giving us a way to talk computationally about planets and human faces and visual feature spaces.
Of course, once we’ve formulated something in computational language, we’re in a position (thanks to the whole knowledgebase and algorithmbase of the Wolfram Language) to actually do a computation about it. And, needless to say, this is extremely powerful. But what’s also extremely powerful is that the computational language itself gives us a way to formulate things in computational terms.
Let’s say we want to know how efficient the Roman numeral system was. How do we formulate that question computationally? We might think about knowing the string lengths of Roman numerals, and comparing them to the lengths of modern integers. It’s easy to express that in Wolfram Language. Here’s a Roman numeral:
✕
RomanNumeral[188] |
And here’s its string length:
✕
StringLength[RomanNumeral[188]] |
Now here’s a plot of all Roman numeral lengths up to 200, divided by the corresponding integer lengths—with callouts automatically showing notable values:
✕
ListLinePlot[Table[ Callout[StringLength[RomanNumeral[n]]/IntegerLength[n], n], {n, 200}]] |
It’s easy enough to make a histogram for all numbers up to 1000:
✕
Histogram[Table[ StringLength[RomanNumeral[n]]/IntegerLength[n], {n, 1000}]] |
But of course in actual usage, some numbers are more common than others. So how can we capture that? Well, here’s one (rather naive) computational approach. Let’s just analyze the Wikipedia article about arithmetic, and see what integers it mentions. Again, that computational concept is easy to express in the Wolfram Language: finding cases of numbers in the article, then selecting those that are interpreted as integers:
✕
Select[IntegerQ][ TextCases[WikipediaData["arithmetic"], "Number" -> "Interpretation"]] |
There are some big numbers, with Roman-numeral representations for which the notion of “string length” doesn’t make much sense:
✕
RomanNumeral[7485696] |
And then there’s 0, for which the Romans didn’t have an explicit representation. But restricting to “Roman-stringable” numbers, we can make our histogram again:
✕
Histogram[ Map[StringLength[RomanNumeral[#]]/IntegerLength[#] &][ Select[IntegerQ[#] && 0 < # < 5000 &][ TextCases[WikipediaData["arithmetic"], "Number" -> "Interpretation"]]]] |
And what’s crucial here is that—with Wolfram Language—we’re in a position to formulate our thinking in terms of computational concepts, like StringLength and TextCases and Select and Histogram. And we’re able to use the computational language to express our computational thinking—in a way that humans can read, and the computer can compute from.
The Difference from Programming Languages
As a practical matter, the examples of computational language we’ve just seen look pretty different from anything one would normally do with a standard programming language. But what is the fundamental difference between a computational language and a programming language?
First and foremost, it’s that a computational language tries to intrinsically be able to talk about whatever one might think about in a computational way—while a programming language is set up to intrinsically talk only about things one can directly program a computer to do. So for example, a computational language can intrinsically talk about things in the real world—like the planet Mars or New York City or a chocolate chip cookie. A programming language can intrinsically talk only about abstract data structures in a computer.
Inevitably, a computational language has to be vastly bigger and richer than a programming language. Because while a programming language just has to know about the operation of a computer, a computational language tries to know about everything—with as much knowledge and computational intelligence as possible about the world and about computation built into it.
To be fair, the Wolfram Language is the sole example that exists of a full-scale computational language. But one gets a sense of magnitude from it. While the core of a standard programming language typically has perhaps a few tens of primitive functions built in, the Wolfram Language has more than 5600—with many of those individually representing major pieces of computational intelligence. And in its effort to be able to talk about the real world, the Wolfram Language also has millions of entities of all sorts built into it. And, yes, the Wolfram Language has had more than three decades of energetic, continuous development put into it.
Given a programming language, one can of course start programming things. And indeed many standard programming languages have all sorts of libraries of functions that have been created for them. But the objective of these libraries is not really the same as the objective of a true computational language. Yes, they’re providing specific “functions to call”. But they’re not trying to create a way to represent or talk about a broad range of computational ideas. To do that requires a coherent computational language—of the kind I’ve been building in the Wolfram Language all these years.
A programming language is (needless to say) intended as something in which to write programs. And while it’s usually considered desirable for humans to be able—at least at some level—to read the programs, the ultimate point is to provide a way to tell a computer what to do. But computational language can also achieve something else. Because it can serve as an expressive medium for communicating computational ideas to humans as well as to computers.
Even when one’s dealing with abstract algorithms, it’s common with standard programming languages to want to talk in terms of some kind of “pseudocode” that lets one describe the algorithms without becoming enmeshed in the (often fiddly) details of actual implementation. But part of the idea of computational language is always to have a way to express computational ideas directly in the language: to have the high-level expressiveness and readability of pseudocode, while still having everything be precise, complete and immediately executable on a computer.
Looking at the examples above, one thing that’s immediately obvious is that having the computational language be symbolic is critical. In most standard programming languages, x on its own without a value doesn’t mean anything; it has to stand for some structure in the memory of the computer. But in a computational language, one’s got to be able to have things that are purely symbolic, and that represent, for example, entities in the real world—that one can operate on just like any other kind of data.
There’s a whole cascade of wonderful unifications that flow from representing everything as a symbolic expression, crucial in being able to coherently build up a full-scale computational language. And to make a computational language as readily absorbable by humans as possible, there are also all sorts of detailed issues of interface—like having hierarchically structured notebooks, allowing details of computational language to be iconized for display, and so on.
Why Not Just Use Natural Language?
Particularly in this age of machine learning one might wonder why one would need a precisely defined computational language at all. Why not just use natural language for everything?
Wolfram|Alpha provides a good example (indeed, probably the most sophisticated one that exists today) of what can be done purely with natural language. And indeed for the kinds of short questions that Wolfram|Alpha normally handles, it proves that natural language can work quite well.
But what if one wants to build up something more complicated? Just like in the case of doing mathematics without notation, it quickly becomes impractical. And I could see this particularly clearly when I was writing an introductory book on the Wolfram Language—and trying to create exercises for it. The typical form of an exercise is: “Take this thing described in natural language, and implement it in Wolfram Language”. Early in the book, this worked OK. But as soon as things got more complicated, it became quite frustrating. Because I’d immediately know what I wanted to say in Wolfram Language, but it took a lot of effort to express it in natural language for the exercise, and often what I came up with was hard to read and reminiscent of legalese.
One could imagine that with enough back-and-forth, one might be able to explain things to a computer purely in natural language. But to get any kind of clear idea of what the computer has understood, one needs some more structured representation—which is precisely what computational language provides.
And it’s certainly no coincidence that the way Wolfram|Alpha works is first to translate whatever natural language input it’s given to precise Wolfram Language—and only then to compute answers from it.
In a sense, using computational language is what lets us leverage the last few centuries of exact science and systematic knowledge. Earlier in history, one imagined that one could reason about everything just using words and natural language. But three or four centuries ago—particularly with mathematical notation and other mathematical ideas—it became clear that one could go much further if one had a structured, formal way of talking about the world. And computational language now extends that—bringing a much wider range of things into the domain of formal computational thinking, and going still further beyond natural language.
Of course, one argument for trying to use natural language is that “everybody already knows it”. But the whole point is to be able to apply computational thinking—and to do that systematically, one needs a new way of expressing oneself, which is exactly what computational language provides.
How Computational Language Leverages Natural Language
Computational language is something quite different from natural language, but in its construction it still uses natural language and people’s understanding of it. Because in a sense the “words” in the computational language are based on words in natural language. So, for example, in the Wolfram Language, we have functions like StringLength, TextCases and FeatureSpacePlot.
Each of these functions has a precise computational definition. But to help people understand and remember what the functions do, we use (very carefully chosen) natural language words in their names. In a sense, we’re leveraging people’s understanding of natural language to be able to create a higher level of language. (By the way, with our “code captions” mechanism, we’re able to at least annotate everything in lots of natural languages beyond English.)
It’s a slightly different story when it comes to the zillions of real-world entities that a computational language has to deal with. For a function like TextCases, you both have to know what it’s called, and how to use it. But for an entity like New York City, you just have to somehow get hold of it—and then it’s going to work the same as any other entity. And a convenient way to get hold of it is just to ask for it, by whatever (natural language) name you know for it.
For example, in the Wolfram Language you can just use a “free-form input box”. Type nyc and it’ll get interpreted as the official New York City entity:
✕
\!\(\*NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "nyc", Typeset`boxes$$ = TemplateBox[{"\"New York City\"", RowBox[{"Entity", "[", RowBox[{"\"City\"", ",", RowBox[{"{", RowBox[{"\"NewYork\"", ",", "\"NewYork\"", ",", "\"UnitedStates\""}], "}"}]}], "]"}], "\"Entity[\\\"City\\\", {\\\"NewYork\\\", \\\"NewYork\\\", \ \\\"UnitedStates\\\"}]\"", "\"city\""}, "Entity"], Typeset`allassumptions$$ = {{"type" -> "Clash", "word" -> "nyc", "template" -> "Assuming \"${word}\" is ${desc1}. Use as ${desc2} instead", "count" -> "2", "Values" -> {{"name" -> "City", "desc" -> "a city", "input" -> "*C.nyc-_*City-"}, {"name" -> "VisualArts", "desc" -> "a photograph", "input" -> "*C.nyc-_*VisualArts-"}}}}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1, 2}, Typeset`querystate$$ = {"Online" -> True, "Allowed" -> True, "mparse.jsp" -> 0.274794`5.890552239367699, "Messages" -> {}}}, DynamicBox[ ToBoxes[AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache -> {173., {7., 15.}}, TrackedSymbols :> {Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues :> {}, UndoTrackedVariables :> {Typeset`open$$}], BaseStyle -> {"Deploy"}, DeleteWithContents -> True, Editable -> False, SelectWithContents -> True]\) |
You can use this entity to do computations:
✕
GeoArea[\!\(\*NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "nyc", Typeset`boxes$$ = TemplateBox[{"\"New York City\"", RowBox[{"Entity", "[", RowBox[{"\"City\"", ",", RowBox[{"{", RowBox[{"\"NewYork\"", ",", "\"NewYork\"", ",", "\"UnitedStates\""}], "}"}]}], "]"}], "\"Entity[\\\"City\\\", {\\\"NewYork\\\", \\\"NewYork\\\", \ \\\"UnitedStates\\\"}]\"", "\"city\""}, "Entity"], Typeset`allassumptions$$ = {{"type" -> "Clash", "word" -> "nyc", "template" -> "Assuming \"${word}\" is ${desc1}. Use as ${desc2} instead", "count" -> "2", "Values" -> {{"name" -> "City", "desc" -> "a city", "input" -> "*C.nyc-_*City-"}, {"name" -> "VisualArts", "desc" -> "a photograph", "input" -> "*C.nyc-_*VisualArts-"}}}}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1, 2}, Typeset`querystate$$ = {"Online" -> True, "Allowed" -> True, "mparse.jsp" -> 0.274794`5.890552239367699, "Messages" -> {}}}, DynamicBox[ ToBoxes[AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache -> {173., {7., 15.}}, TrackedSymbols :> {Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues :> {}, UndoTrackedVariables :> {Typeset`open$$}], BaseStyle -> {"Deploy"}, DeleteWithContents -> True, Editable -> False, SelectWithContents -> True]\)] |
Of course, this kind of free-form input can be ambiguous. Type ny and the first interpretation is New York state:
✕
\!\(\*NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "ny", Typeset`boxes$$ = TemplateBox[{"\"New York, United States\"", RowBox[{"Entity", "[", RowBox[{"\"AdministrativeDivision\"", ",", RowBox[{"{", RowBox[{"\"NewYork\"", ",", "\"UnitedStates\""}], "}"}]}], "]"}], "\"Entity[\\\"AdministrativeDivision\\\", {\\\"NewYork\\\", \ \\\"UnitedStates\\\"}]\"", "\"administrative division\""}, "Entity"], Typeset`allassumptions$$ = {{"type" -> "Clash", "word" -> "ny", "template" -> "Assuming \"${word}\" is ${desc1}. Use as ${desc2} instead", "count" -> "2", "Values" -> {{"name" -> "USState", "desc" -> "a US state", "input" -> "*C.ny-_*USState-"}, {"name" -> "City", "desc" -> "a city", "input" -> "*C.ny-_*City-"}}}}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1, 2}, Typeset`querystate$$ = {"Online" -> True, "Allowed" -> True, "mparse.jsp" -> 0.321865`5.9592187470275455, "Messages" -> {}}}, DynamicBox[ ToBoxes[AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache -> {333., {7., 15.}}, TrackedSymbols :> {Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues :> {}, UndoTrackedVariables :> {Typeset`open$$}], BaseStyle -> {"Deploy"}, DeleteWithContents -> True, Editable -> False, SelectWithContents -> True]\) |
Press the little dots and you get to say you want New York City instead:
✕
\!\(\*NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "nyc", Typeset`boxes$$ = TemplateBox[{"\"New York City\"", RowBox[{"Entity", "[", RowBox[{"\"City\"", ",", RowBox[{"{", RowBox[{"\"NewYork\"", ",", "\"NewYork\"", ",", "\"UnitedStates\""}], "}"}]}], "]"}], "\"Entity[\\\"City\\\", {\\\"NewYork\\\", \\\"NewYork\\\", \ \\\"UnitedStates\\\"}]\"", "\"city\""}, "Entity"], Typeset`allassumptions$$ = {{"type" -> "Clash", "word" -> "nyc", "template" -> "Assuming \"${word}\" is ${desc1}. Use as ${desc2} instead", "count" -> "2", "Values" -> {{"name" -> "City", "desc" -> "a city", "input" -> "*C.nyc-_*City-"}, {"name" -> "VisualArts", "desc" -> "a photograph", "input" -> "*C.nyc-_*VisualArts-"}}}}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1, 2}, Typeset`querystate$$ = {"Online" -> True, "Allowed" -> True, "mparse.jsp" -> 0.274794`5.890552239367699, "Messages" -> {}}}, DynamicBox[ ToBoxes[AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache -> {173., {7., 15.}}, TrackedSymbols :> {Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues :> {}, UndoTrackedVariables :> {Typeset`open$$}], BaseStyle -> {"Deploy"}, DeleteWithContents -> True, Editable -> False, SelectWithContents -> True]\) |
For convenience, the inputs here are natural language. But the outputs—sometimes after a bit of disambiguation—are precise computational language, ready to be used wherever one wants.
And in general, it’s very powerful to be able to use natural language to specify small chunks of computational language. To express large-scale computational thinking, one needs the formality and structure of computational language. But “small utterances” can be given in natural language—like in Wolfram|Alpha—then translated to precise computational language:
✕
\!\(\*NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "population of nyc", Typeset`boxes$$ = RowBox[{TemplateBox[{"\"New York City\"", RowBox[{"Entity", "[", RowBox[{"\"City\"", ",", RowBox[{"{", RowBox[{"\"NewYork\"", ",", "\"NewYork\"", ",", "\"UnitedStates\""}], "}"}]}], "]"}], "\"Entity[\\\"City\\\", {\\\"NewYork\\\", \\\"NewYork\\\", \ \\\"UnitedStates\\\"}]\"", "\"city\""}, "Entity"], "[", TemplateBox[{"\"city population\"", RowBox[{"EntityProperty", "[", RowBox[{"\"City\"", ",", "\"Population\""}], "]"}], "\"EntityProperty[\\\"City\\\", \\\"Population\\\"]\""}, "EntityProperty"], "]"}], Typeset`allassumptions$$ = {}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1, 2}, Typeset`querystate$$ = {"Online" -> True, "Allowed" -> True, "mparse.jsp" -> 0.701535`6.297594336611864, "Messages" -> {}}}, DynamicBox[ ToBoxes[AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache -> {291., {11., 18.}}, TrackedSymbols :> {Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues :> {}, UndoTrackedVariables :> {Typeset`open$$}], BaseStyle -> {"Deploy"}, DeleteWithContents -> True, Editable -> False, SelectWithContents -> True]\) |
✕
EntityClass[ "City", {EntityProperty["City", "Population"] -> TakeLargest[5]}] // EntityList |
✕
Plot[Cos[x], {x, -6.6, 6.6}, PlotStyle -> Purple] |
What Computational Language Makes Possible
I think by now there’s little doubt the introduction of the computational paradigm is the single most important intellectual development of the past century. And going forward, I think computational language is going to be crucial in being able to broadly make use of that paradigm—much as many centuries ago, mathematical notation was crucial to launching the widespread use of the mathematical paradigm.
How should one express and communicate the ideas of a “computational X” field? Blobs of low-level programming language code won’t do it. Instead, one needs something that can talk directly about things in the field—whether they are genes, animals, words, battles or whatever. And one also needs something that humans can readily read and understand. And this is precisely what computational language can provide.
Of course, computational language also has the giant bonus that computers can understand it, and that it can be used to specify actual computations to do. In other words, by being able to express something in computational language, you’re not only finding a good way to communicate it to humans, you’re also setting up something that can leverage the power of actual computation to automatically produce things.
And I suspect that in time it will become clear that the existence of computational language as a communication medium is what ultimately succeeded in launching a huge range of computational X fields. Because it’s what will allow the ideas in these fields to be put in a concrete form that people can think in terms of.
How will the computational language be presented? Often, I suspect, it will be part of what I call computational essays. A computational essay mixes natural language text with computational language—and with the outputs of actual computations described by the computational language. It’s a little like how for the past couple of centuries, technical papers have typically relied on mixing text and formulas.
But a computational essay is something much more powerful. For one thing, people can not only read the computational language in a computational essay, but they can also immediately reuse it elsewhere. In addition, when one writes a computational essay, it’s a computer-assisted activity, in which one shares the load with the computer. The human has to write the text and the computational language, but then the computer can automatically generate all kinds of results, infographics, etc. as described by the computational language.
In practice it’s important that computational essays can be presented in Wolfram Notebooks, in the cloud and on the desktop, and that these notebooks can contain all sorts of dynamic and computational elements.
One can expect to use computational essays for a wide range of things—whether papers, reports, exercises or whatever. And I suspect that computational essays, written with computational language, will become the primary form of communication for computational X fields.
I doubt we can yet foresee even a fraction of the places where computational language will be crucial. But one place that’s already clear is in defining computational contracts. In the past, contracts have basically always been written in natural language—or at least in the variant that is legalese. But computational language provides an alternative.
With the Wolfram Language as it is today, we can’t cover everything in every contract. But it’s already clear how we can use computational language to represent many kinds of things in the world that are the subject of contracts. And the point is that with computational language we can write a precise contract that both humans and machines can understand.
In time there’ll be computational contracts everywhere: for commerce, for defining goals, for AI ethics, and so on. And computational language is what will make them all possible.
When literacy in natural language began to become widespread perhaps 500 years ago, it led to sweeping changes in how the world could be organized, and in the development of civilization. In time I think it’s inevitable that there’ll also be widespread literacy in computational language. Certainly that will lead to much broader application of computational thinking (and, for example, the development of many “computational X” fields). And just as our world today is full of written natural language, so in the future we can expect that there will be computational language everywhere—that both defines a way for us humans to think in computational terms, and provides a bridge between human thinking and the computation that machines and AIs can do.
How Come It’s So Unique?
I’ve talked a lot about the general concept of computational language. But in the world today, there’s actually only one example that exists of a full-scale computational language: the Wolfram Language. At first, it might seem strange that one could say this so categorically. With all the technology out there in the world, how could something be that unique?
But it is. And I suppose this becomes a little less surprising when one realizes that we’ve been working on the Wolfram Language for well over thirty years—or more than half of the whole history of modern computing. And indeed, the span of time over which we’ve been able to consistently pursue the development of the Wolfram Language is now longer than for almost any other software system in history.
Did I foresee the emergence of the Wolfram Language as a full computational language? Not entirely. When I first started developing what’s now the Wolfram Language I wanted to make it as general as possible—and as flexible in representing computational ideas and processes.
At first, its most concrete applications were to mathematics, and to various kinds of modeling. But as time went on, I realized that more and more types of things could fit into the computational framework that we’d defined. And gradually this started to include things in the real world. Then, about a decade and a half ago, I realized that, yes, with the whole symbolic language we’d defined, we could just start systematically representing all those things like cities and chemicals in pretty much the same way as we’d represented abstract things before.
I’d always had the goal of putting as much knowledge as possible into the language, and of automating as much as possible. But from the beginning I made sure that the language was based on a small set of principles—and that as it grew it maintained a coherent and unified design.
Needless to say, this wasn’t easy. And indeed it’s been my daily activity now for more than 30 years (with, for example, 300+ hours of it livestreamed over the past year). It’s a difficult process, involving both deep understanding of every area the language covers, as well as a string of complicated judgement calls. But it’s the coherence of design that this achieves that has allowed the language to maintain its unity even as it has grown to encompass all sorts of knowledge about the real world, as well as all those other things that make it a full computational language.
Part of what’s made the Wolfram Language possible is the success of its principles and basic framework. But to actually develop it has also involved the creation of a huge tower of technology and content—and the invention of countless algorithms and meta-algorithms, as well as the acquisition and curation of immense amounts of data.
It’s been a strange mixture of intellectual scholarship and large-scale engineering—that we’ve been fortunate enough to be able to consistently pursue for decades. In many ways, this has been a personal mission of mine. And along the way, people have often asked me how to pigeonhole what we’re building. Is it a calculation system? Is it an encyclopedia-like collection of data? Is it a programming language?
Well, it’s all of those things. But they’re only part of the story. And as the Wolfram Language has developed, it’s become increasingly clear how far away it is from existing categories. And it’s only quite recently that I’ve finally come to understand what it is we’ve managed to build: the world’s only full computational language. Having understood this, it starts to be easier to see just how what we’ve been doing all these years fits into the arc of intellectual history, and what some of its implications might be going forward.
From a practical point of view, it’s great to be able to respond to that obvious basic question: “What is the Wolfram Language?” Because now we have a clear answer: “It’s a computational language!” And, yes, that’s very important!