The Will and the Word
A Philosophy of Programming

Version 1.3.0a2:6
by Jim Little


Introduction

What is programming? It's a question that's rarely asked. And when it is asked, the answer usually involves statements about "logic" or "source code". But I think the question isn't getting the attention it deserves. Nor do the common answers do justice to this complex issue.

Programs themselves are an ethereal concept. Sure, if you ask a programmer to show you her program, she'll point you to a ream of paper filled with cryptic symbols. But in reality, that source code isn't the program. When you buy a CD with a program on it, you rarely get the source code. The nature of programs is more complex than just source code or windows on a computer monitor.

In this paper, I explore the nature of programs and programming. My primary hypothesis is illustrated by analogy with the magic in David Eddings' Belgariad books. In Mr. Eddings' books, spells are cast with "the Will and the Word." The wizard gathers her Will (identifies what she wants to do) and releases it with a Word. Similarly, I contend that programmers create programs by gathering their Will (identifying a program to create) and expressing it with a "Word" (source code). The important part of this analogy is that the Will of the programmer -- her program -- is separate from the Word of the programmer -- her source code.


The Will and the Word

What is a program? At first glance, the answer seems simple. A programmer will point to her source code when asked what a program is. But the answer isn't quite so simple. If you could look inside the computer while it was running the program, the programmer's source code would be nowhere in sight.

But how can this be possible? Upon further questioning, the programmer will admit that her source code isn't actually given to the user. Instead, it's processed by a compiler into machine code. The programmer will say that the machine code is her program, too.

I contend that none of these things are actually programs. Instead, the programmer's source code and the automatically-generated machine code are both representations -- models -- of the actual program. Different models, representing the same program.

If source code and machine code are nothing more than models of a program, then what's a program? I contend that programs are just concepts. The desire for a computer to behave in a certain way. The Will of the programmer.

This all sounds very grandiose. But the problem with saying that programs are nothing more than a programmer's Will is that it doesn't explain how programs execute. Computers run programs, and they don't do it by magically figuring out what the programmer wants! (Far from it.)

This is where the programmer's Word comes in. Having "gathered her Will" by deciding what the computer needs to do, the programmer expresses that Will with her Word. Specifically, by writing source code. In less fantastic language, the programmer conceives a program and then models it with source code.

That source code is transformed into machine code and fed to the computer, which executes it. It's important to note that the transformation is isomorphic -- both models (source code and machine code), though widly different in appearance, represent the same program.


The Eye of the Beholder

Given a model, observers must determine which program that model represents. This process is called decoding the model. To decode a model, the observer first determines the model's code. Then the observer applies her understanding of the code to decode the model. A "code" is a conceptual system for interpreting models. (Note that the word "code" is used here in the semiotic sense, not in the programming sense.)

Models can be interpreted using any code the observer wishes, but only one code will reveal the correct program. That code, which I call the model's canonical code, is the code used by the model's originator to originally create the model. It's the code with which the model was encoded. In order for the observer to correctly determine which program a model represents, she must use the model's canonical code.

This gives rise to two challenges. First, the observer must somehow determine the canonical code of the model. Second, the observer must understand the canonical code. That is, she must be able to apply it and so decode the model.

The canonical code of a model can often be determined from contextual clues: the name of a file, unique patterns within the model, etc. For example, the canonical code of a file named "foo.c" is probably C source code. Clearly, though, the more easily a model's canonical code may be determined, the better the chances of it being decoded correctly.

Even if a model's canonical code can be determined, the observer must understand the code well enough to decode the model. For example, it does a programmer no good to understand that a model is encoded with C if she doesn't know C!

This point brings us to the concept of metamodels. Metamodels describe codes. Once an observer completely decodes a metamodel, she gains complete understanding of the code it represents. This allows her to decode any model encoded with that code.

Metamodels may seem like unlikely concepts, but in reality they're quite common. For example, the C language specification is a metamodel. Once a programmer has decoded the C language specification, she understands C code. She can use that knowledge to decode any model encoded with C code. (In theory, anyway. In practice, the programmer must also understand the C standard library, the C preprocessor, and OS-specific API's. But why muck up a good example with such complex issues?)


Reaching an Understanding

The concept of a human programmer "understanding" a code makes sense. But what does it mean for a computer metaprogram, such as a compiler, to understand a code? No program today has a human-like understanding of anything.

The answer is that, although a metaprogram can't have a human-like understanding of a code, it can have a limited, task-specific understanding. It doesn't gain that understanding by interpreting a metamodel, though; it gains that understanding by having it programmed in by a programmer. The programmer is the one who must interpret the metamodel. Once she has done so, she has an understanding of a particular code, and may create metaprograms that operate on that code's models.


Beyond the Beyond

Up until now, I've been using the word "model" to mean "a concrete representation of a program." In actuality, a model can be a concrete representation of anything.

I mention this because metamodels are themselves models. They're not models of programs; they're models of codes. When an observer decodes a metamodel, understanding of a code is the result, just as when a regular program model is decoded, understanding of a program is the result.

Since metamodels are themselves models, they too have canonical codes. These metacodes allow the observer to understand other codes. Metacodes in turn are modeled by meta-metamodels.

If all this "meta-this" and "meta-that" seems confusing, don't worry... it is! To summarize the story thus far:

  1. Programs are concepts.
  2. Concepts are abstract. They're physically represented with models.
  3. To determine which concept a model represents, known as decoding the model, the observer uses a code.
  4. Codes are concepts. They're physically represented with metamodels.
  5. To decode a metamodel, the observer uses a metacode.
  6. Metacodes are concepts. They're physically represented with meta-metamodels.

We could continue the chain, adding "meta" prefixes to the point of ridiculousness, if we wanted. But in practice, metacodes and meta-metamodels seem to be as much as we need. Natural language (such as English) takes over after that.

Metacodes, though, are still pretty useful. If you start with a model, then a metacode is nothing more than part of the way you understand that model. But if you start with a metacode, it becomes a structure which defines the way you define metamodels and models. And that is very useful, because a metacode can impose a consistent structure on a set models that transcends the specific codes with which those models were created.

Since all of the models for a particular metacode share characteristics defined by that metacode, metaprograms that are designed to operate on those common characteristics can work on models from multiple codes. Right now, metaprograms typically only operate on one sort of code. But with the proper metacode, that need not be so.

A metacode could even go so far to restrict its metamodels to being machine readable. With such a metacode, metaprograms could be written that work for any of the metacode's metamodels. Since the metacode's metamodels would be machine readable, the metaprogram would read in the appropriate metamodels as well as the model to be manipulated. For example, a compiler would read in the source and target metamodel, along with the source model, and automatically configure itself to perform the compilation.

Such a metacode would be extremely useful, because each category of metaprogram would only need to be written once, rather than over and over for each individual code. On the other hand, such a metacode implies the creation of a machine-readable syntax and semantics descriptions. While machine-readable syntax descriptions are no problem, I don't know if a general-purpose machine-readable semantics description is feasible.


Conclusion

The purpose of this essay was solely to induce some thoughts on the nature of programs and programming. I provided some definitions and concepts that attempted to get to the core of the issue, to ferret out the true nature of programs. It's for you to decide if I succeeded on that score, but if I made you pause for a moment and wonder, then I was successful in my larger goal.

On a more mundane level, the primary point of this essay was that programs are concepts, not physical entities. Programs are the concept that a computer will behave in a certain way.

Physical representations of programs are models. A single program may be represented by several different models. To determine which model a program represents, you must first determine its canonical code -- the code it was encoded with -- and then decode it with that code.

Codes are themselves concepts, and they are also represented with models. Models of codes are called metamodels. To decode a metamodel, you use its canonical code. The codes of metamodels are called metacodes, and they're represented with meta-metamodels.

Metacodes can control how metamodels are created, and thus cause models to have a common structure, even if they have different codes. This can lead to metaprograms that operate on models regardless of their code. Furthermore, if a metacode could be created that specified machine-readable semantics as well as syntax, much more powerful tools could be created. However, it may not be possible for human semantics to be machine-readable.


Acknowledgements

Many thanks to the members of the Prism list for their feedback on the previous revision of this essay. Special thanks go out to Laurent Martelli and Anders Petersson, whose comments led to the new "Reaching an Understanding" portion of this essay. Anders was particularly eloquent:

Maybe understanding has to be ruled from the results. In such case, it's clear programs understand the models they succeed in translating. What is then the difference from our way of understanding? We read a meaning into the contents - but so do programs. Maybe the difference is *what* meaning we can read into the data. Programs only know enough to map it into some other domain, while we give it a meaning in relation to the rest of the world (which programs don't know about at all!) - and subsequently have a potentially greater use of the information.

Thanks to you both.


Contact: Jim Little
Published: 22 December 1999 -- Revision History
Copyright 1999 by Jim Little. Please read this copyright notice before redistributing or using.

Home