wiki.paulswartz.net

Navigation

Recent site activity

Home‎ > ‎DivisionIII‎ > ‎

How do Programs Mean

For natural language texts, the idea of meaning is a complex one. Philosophers and theorists all have their ideas about how meaning is derived from words and sentences. In English, the basis for discussing communication of meaning is the conduit metaphor. Explicated originally by Michael Reddy, the conduit metaphor has four major ideas:

  1. Language functions like a conduit, transferring thoughts bodily from one person to another;
  2. In writing and speaking, people insert their thoughts or feelings in the words;
  3. Words accomplish the transfer by containing the thoughts or feelings and conveying them to others; and
  4. In listening or reading, people extract the thoughts and feelings once again from the words.[1]

With this metaphor, we talk about language as if it were a pipe, into which we put boxes of meaning, that are transferred to another person in a conversation, who opens the box and takes out the meaning. We speak of communication in words (already I'm writing about words as a container) and phrases like “put more thought into what you say.” Although this is a metaphor for how we speak, these kinds of linguistic metaphors are more than literary flourishes – they structure our very consciousness. They "structure what we perceive, how we get around in the world, and how we relate to people. Our conceptual system thus plays a central role in defining our everyday realities."[2] The conduit metaphor is the structuring metaphor for our concept of meaning and communication.

The conduit metaphor makes our communications with others possible. By believing that the ideas in our heads can be conveyed to other people through language, we attempt (and often succeed) to communicate. No culture can believe that the communication of ideas is impossible. The very definition of culture requires humans to communicate with each other. Culture develops around shared ideas, and shared ideas are communicated through language.

The conduit metaphor also simplifies our everyday interactions with other people. Meaning is such an elusive concept, one that pulls in so much outside of the words, that “metaphorizing” it into a physical object restrains it, controls it, makes it manageable. Written language makes this physicality obvious, since we always have an object when we have a writing. Even spoken language has a degree of physicality: because the other person must be there to transmit the words, the person is the physical representation of the words they are uttering.

However, this metaphor is not literally true. Words are not physical objects, containers for meaning objects; we just treat them that way. Translation is difficult for exactly this reason: the meaning is also in the context and in the society in which the statements are uttered. Translators need to know more than just the grammar and the syntax; they need to be able to think in both languages. There is also the problem that we do not know how our words are decoded at the other end.

The conduit metaphor simplifies this with the assumption that the meaning we put into the words is the same meaning that is taken out by the other party, but this is obviously untrue. Since no two people are identical, the contexts into which the two parties put the words are different. When the words are unpacked, they are unpacked into different contexts and have different meanings.

Computer code can also be seen as a language, and the problem of meaning is no less complicated. Programming statements, unlike natural language statements, can be seen as a literal extension of this metaphor. The code that a computer reads is sent through the conduit of a keyboard or read through the cables of a hard drive. The electrical pulses that flow through the processor are tiny physical objects, weighing less than the lightest atom.

However, the computer does more to complicate the metaphor than it does to uphold it. No feelings are embedded into the program code; programs written angrily and programs written happily work the same when it comes to the computer. This is because the words the computer understands have designated meanings in the grammar of the language. For example, in Python the equal sign (=) is defined as creating a reference to the right-hand side with the name on the left-hand side. When it appears in the code, it always has that meaning. The computer does not draw any thought out of the code it parses; it only understands the words that the language has predefined. We do not put any of our feelings into the words we send to the computer, but we can draw meaning out of what the computer does with those words. The computer only has one context; whatever the code does when it is executed is what that code means to the computer.

The conduit metaphor is a structuring of language use: what of the structure of language itself? In the opening years of the 20th century, Ferdinand de Saussure gave a course that would change the path of linguistics by creating the new field of structuralist linguistics. His Course in General Linguistics was a reaction to the (then current) study of linguistics as an historical study of a language: how words came to mean what they mean by tracing their evolution through history.

Saussure saw language as composed of two related parts: langue, which is the structure of language, and parole which is the use of that structure. Langue is the abstract structure of language that is used when one speaks/writes; one can attempt (as Chomskyan generative-grammar linguists have) to derive it from how the language is used, but such attempts are inevitably imperfect. Langue is a collection of signs, which are themselves composed of a signifier (generally a word) and a signified (a sound-image or an idea). The system of signs is organized as a series of oppositions: male/female, happy/sad, red/green/blue. There are no terms that positively define other words. The value of a word is defined only by what it is not: a cat is not a dog or a human, nor is it a bat or a mat. The most powerful oppositions in Western culture are binary distinctions, but they are also the most problematic. They are powerful because they are simple; by only involving two signs, the two objects are easily opposed. Problems arise when the comparisons are not that simple: not all categories can be reduced to a binary.

Computers actually reverse the structuralist relationship between langue and parole. As Walter J. Ong writes in the first chapter of Orality and Literacy,

Computer languages rules ('grammar') are stated first and thereafter used. The rules of grammar in natural human languages are used first and can be abstracted from usage and stated explicitly in words only with difficulty and never completely.[3]

The first thing that programmers learn about a language is generally not how others have used the language, but how the language is defined. This is possible because artificial languages have the advantage (as described above) of having an accessible langue in the form of the grammar and syntax definitions. The parole, the use of the language, only makes sense after a programmer knows the langue.

The grammars of natural languages are not directly accessible. It is only inside of our unconscious mind that these rules exist. Therefore, teaching those rules directly is impossible: we do not have direct access to our unconscious. There is no set of rules that we learn in order to speak English; we learn the grammar experientially, through the parole (other people's speaking or writing). That is our only access to our grammar.

The fundamental binary distinction in computer science is the bit: 1 or 0, on or off, true or false. Technically, it is merely an analog voltage that is either high or low, but it functions as a binary. Everything in the digital computer is based around the bit. Bits are combined with logic gates: AND (on if both input bits are both on), OR (on if either of the input bits are on) and NOT (on if the input bit is off). These logic gates are then combined into the chips that are inside all of our electronic devices. Because of this, the binary distinction of the bit structures all the interactions that are possible with the computer. Characters are represented as a series of eight bits; real numbers are generally stored as 32 bits in a format known as a floating-point number (because the location of the decimal point in the representation floats, based on the amount of precision needed).

However, the binary opposition and the bit can also been seen as a binary opposition. The real numbers cause a problem for representations using bits because some numbers, i.e. repeating decimals or irrational numbers, cannot be perfectly represented by any length string of binary digits. These are numbers that can only be approximated with bits. Those numbers are signs in the parole, structured by binary oppositions.

The computer's basis in mathematics and logic shows through here. Language can more easily handle infinitely long numbers because humans can abbreviate the numbers in their heads; computers have to store them somehow. Numbers can be stored in a representation that allows for infinitely long numbers, but the more accurate the representation gets, the closer it gets to being simply a representation of the linguistic form. Computers do not directly operate at that level, so any operation requires the computer to execute many more operations.

If the computer is not based on linguistic binary oppositions, can the code be seen as a signifier or a signified, or perhaps something in between? The signifier is the surface we interact with, and the signified is what that signifier means to us when we interact with that surface. Code is not entirely either signifier or signified; it possesses qualities of both. It is a surface, since we can interact with the words directly; we can write them down, erase them, move them around, speak them aloud. But it is also meaning: the computer does what the code says. Perhaps this inability to make a distinction in code between signifier and signified is because with code, the link between signifier and signified is not arbitrary, as it is in natural language. The links are chosen explicitly by a language developer, not evolved over time through use. The computer understands each word because a developer programmed what the computer will do when it is told to execute that word. Each word in the programming language means what it does.

The idea of words meaning what they do was first explained by J.L. Austin. In How to Do Things with Words, he writes against the interpretation of language as purely descriptive. Statements are descriptions of the world, and can be true or false. But not all grammatical sentences are statements: when I told my committee "I promise to have this draft to you by next Monday," I'm not making a description of the world. This type of utterance Austin calls a performative: it says something, but more importantly, it does something in the world. Promises, bets, and marriage ceremonies all fall into this class.

Computer code is also a kind of performative utterance. When the computer interprets a line of code that a programmer has written, the computer does something. It is a description of an action, but it also causes that action to occur when it is read by the computer. Lists of directions are not usually performative utterances, e.g. reading a cake recipe does not create a cake. But lists of directions given to the computer in the correct format is performative, and that performance is the only thing the computer is designed for.

There are (as always) some complications in this relationship. A performative in natural language does its work when it is uttered. When a judge states “I sentence you to 20 years in prison,” you are sentenced as the utterance occurs. In general, this is not true of code statements. They are not uttered aloud; they are always written. Also, the lists of instructions are generally stored in memory and then read later; hence the more specific name for the computers we use today: stored-program digital electronic computers. Instead of functioning at the moment of their creation, they function later, when the instructions are read by the computer.

Compiled languages (those that require a step to translate the source code into object code) are the best example of this. At the moment of creation, code in a compiled language is meaningless to the computer. Only through the translation of a complier can the computer execute the statements. This also means that compiled languages can only act on language information that is available at the time the code is compiled . They can read external files, but the code is not available.

Interpreted languages function differently: they are run through an intermediate interpreter that translates the code into object code immediately. This gives interpreted languages the power to execute code as it is written, a power that programmers can take advantage of. Specifically, programmers can write code that relies on information that can only be determined at the time the program runs: for example, an interpreted language can use dynamic typing, where the type of a variable is not known until run time.

There is also a distinction in some programming languages between performative expressions and statements. Expressions calculate values or call procedures[4]; statements affect or control the execution of statements or expressions.[5] In Python, 'print _____' (printing) is a statement, but 'x()' (function execution) is an expression. Expressions are more performative because they actually perform actions; the function execution could make a calculation or send something over the network. The statement only makes a statement about the context the code is running in: 'print _____ to the screen'. Unlike English, expressions and statements are not always grammatically similar: there are places that an expression can go that a statement cannot. In the assignment statement above, only an expression can appear in the blank. If a programmer were to write a statement in that position, the line would be grammatically incorrect.

In addition to their ability to change the world into which they are uttered, performatives differ from regular statements in other ways. For one, performatives cannot be true or false: "we may say, not indeed false but in general unhappy."[6] A statement, such as “the sky is blue today” can be true or false. The performative ”I do” in a marriage ceremony is not false if I cannot marry the person to whom I say it, it is unhappy. To be happy, there are a number of conditions that a performative must meet:

(Α. 1) There must exist an accepted conventional procedure having a certain conventional effect, that procedure to include the uttering of certain words by certain persons in certain circumstances, and further,
(Α. 2) the particular persons and circumstances in a given case must be appropriate for the invocation of the particular procedure invoked.
(Β. 1) The procedure must be executed by all participants both correctly and
(Β. 2) completely.
(Γ. 1) Where, as often, the procedure is designed for the use by persons having certain thought or feelings, or for the inauguration of certain consequential conduct on the part of any participant, then a person participating in and so invoking the procedure must in fact have those thoughts or feelings, and the participants must intend so to conduct themselves, and further
(Γ. 2) must actually so conduct themselves subsequently.[7]

These also represent errors that occur in computer code. An “Α. 1” error would be trying to reference a variable or a function that does not exist. In compiled languages, this would be a syntax error. This is a key difference between the unhappiness of performatives and the errors of programs. Unhappiness in performative utterances are never grammatical or syntactic errors; they are only errors of function. They are still valid sentences even when they do not perform their function.

The same is not true of programs. "Α. 2” errors do not have a specific name in programming because they are handled differently by different languages and by different programmers. The closest equivalent would be a violation of preconditions, which are the conditions which a function requires are true before it will execute. This is rarely enforced directly by the language, but rather enforced by the function. Before it does its work, it will check the arguments it received and validate them, returning an error if they are not valid. For example, a mathematical function which only operates on positive integers will check that its argument is greater than 0, and return an error if it is not.

The Α class errors are errors of context; the people and statements involved have to be proper to allow the performative to be executed correctly. The Β class errors are errors of performance. These errors do not typically occur with computer code. The only events that keep code from executing correctly and completely are hardware errors, the linguistic equivalent of sudden alexia (the inability to understand language).

Code can plan somewhat for hardware errors, but mostly it depends on the hardware doing its job correctly and completely. The Γ errors are also difficult to apply to code. Those rules are designed to apply to performatives like promises, which fail to function if the person making the promise does not intend to fulfill it, say by crossing his fingers behind his back. However, this requires that the utterer of the performative have an ability to say one thing and do another. Computers do not have this ability, and can only do exactly what they are told. What the programmer intends to do is irrelevant in the realm of code as well; all that matters are the bits in the processor.

This is actually a subtle example of the biggest difference between the use of language by humans and computers: tolerance of ambiguity. Performatives, which "as utterances...are also heir to certain other kinds of ill which infect all utterances,"[8] are grammatical sentences even when they are ambiguous. Lines of code are not and cannot be ambiguous. What the computer does with a line of code is the meaning of that line. It can be ambiguous in way if what the programmer believes will happen is different from what does happen, but this is a different kind of ambiguity, the kind where two people talking use a word to mean different things.

In C, there are often bugs because of this kind of error. There is a difference in C between '=' (assignment) and '==' (checking for equality). However, both of these operations can appear in the same syntactic places. This leads to bugs where the programmer writes: 'if (A = B) do_something();' What the programmer intends is to check if A and B are equal, and if they are, execute do_something(). What that line actually means to the computer is 'assign the value of B to A, and execute do_something()' (because assignment is always true). Computers cannot tolerate the kind of ambiguity where a word has two different but equally possible (in the grammar and syntax of the language) meanings.

So where does this leave the meaning in code? The meaning, like the conduit metaphor assumes, is in the words that the programmers write into the computer. But that is only part of the meaning. There is also meaning in the grammar and syntax definitions of the language, in the way that the computer parses those words into the bits that it can process. And the meaning exists in the actions that the computer takes when it executes those bits.

What we have definitely found, however, is where the meaning does not lie: with the programmer. It starts, perhaps, with the programmer, but it does not remain there. The programmer can model the computer's interaction with the code before it is written, but she can not influence that interaction while the code is running. It is quite astounding how well these theories can be adapted to the artificial languages of computers.

Neither Reddy, Saussure, nor Austin considered computers when they were writing. And yet, their theories are able to draw so much from code. Perhaps this is because the artificial languages to which I have applied their theories are modeled, quite closely at times, on the languages that humans speak. COBOL, for example, was designed to be close to written English to make it easy for programmers. The words in programs function differently than the words in human languages: COBOL's English-like grammar and syntax, in the end, just made programming more complicated.

Computer languages are directed and receive meaning from a collection of electronics. That meaning has been shaped by the humans who created the languages and the computers, and who are themselves always embedded in language. The programmers and language developers use the languages Reddy, Saussure, and Austin studied, and the computer languages they create cannot help but be based on those natural languages.

This is why these theories are so fruitful in the realm of computers and why, in the end, the languages of computers and humans are not so different. We use language and computers differently because it is expedient to do so: it is difficult (currently impossible) to teach a computer to speak a natural language with anything near the fluency of a human. But it is equally difficult (currently impossible) to make a human perform tasks as rapidly and as accurately as a computer. The languages are different because to function we require different results. But as computers get better and as humans get smarter, I presume that the languages will not be as different as they are today.

Notes

  1. Reddy, Michael. "The conduit metaphor: a case of frame conflict in our language about language." Metaphor and thought. ed. Andrew Ortony. Cambridge: Cambridge University Press, 1993. 164-201. p. 170.
  2. Lakoff, George, and Mark Johnson. Metaphors We Live By. Chicago: University Of Chicago Press, 1980. p. 3.
  3. Ong, Walter. Orality and Literacy. New York: Routledge, 2002. p. 7.
  4. "6.1 Expression statements." Python Reference Manual. 19 Sept. 2006. 18 Apr. 2007 <http://www.python.org/doc/current/ref/exprstmts.html>.
  5. "7. Compound statements." Python Reference Manual. 19 Sept. 2006. 18 Apr. 2007 <http://www.python.org/doc/current/ref/compound.html>.
  6. Austin, J.L. How to do things with words. Cambridge: Harvard University Press, 1975. p. 14.
  7. Ibid. pp. 14-5.
  8. Ibid. p. 21.