Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
The art of programmers: an introduction 1. Why study the art of programmers Information and communication technology (ICT) has practically invaded every aspect of human life and culture. In life, ultrasound machines watch over us before we are born, mobile phones and laptops follow us everywhere, and machines such as pacemakers are with us even in death. Culturally, ICT is revolutionizing communication, collaboration, and other human practices at work and at home. Children play at their computer for days on end; the “dot.com”-bubble created and destroyed a new economy; SMS language is gradually creeping into other linguistic practices; and everybody from US presidential candidates to religious fanatics communicate and build societies on the internet. ICT has become part of who we are, and that makes ICT an important area of study in the humanities. But, technology itself does not change our culture. It is the men behind the technological systems who initiate new cultural forms and practices, not the systems themselves. That makes these men collectively the most disruptive and powerful agents of cultural change, and studies of ICT and cultural change should therefore scrutinize these technological systems’ processes of becoming, the men creating them, and these men’s artistic means and culture. In ICT, the men behind the technological systems are commonly referred to as programmers. To study their systems’ processes of becoming and their culture is to study the art of programmers, and taking this approach can give a glimpse of what goes on behind the stage of apparent cultural change. From studying the art of programmers we can gain an understanding of the processes driving ICT, and with this insight we can improve the practices and ethics of computer systems during development and use. 2. Computer programming as writing To program computers essentially means to write program texts. These texts greatly resemble other forms of written communication as alphabetical symbols on an empty slate. 1 But, unlike the ink and paper texts so ingrained in our culture, program texts are embodied in a new, twinned medium: software and hardware. Program texts live their entire lives as electronic impulses stored on magnetic tape (software) or as metal fillings etched in silicon stone (hardware). These new media are foreign to our culture, and so, by the power of association, computer programming is also regarded as an alien cultural practice. This introduction aims to break this association and to recast the alien practice of programming as the familiar practice of writing texts. To reach this goal, a two-part analysis is performed. First, a computer program and the intertextual relations saturating it are analyzed. This intertextual analysis illustrates how computer programs literally function as program texts and how the meaning of program words is reciprocally constructed. Second, and based on this intertextual analysis, the practice of writing program texts is analyzed. This analysis shows how computer programmers envisage their program texts as operating in an intertextual environment and how the conventions of this environment enable and constrain the programmers’ imaginations. The analysis in this introduction builds on a simple Prolog program running on a Prolog interpreter written in Java jTrolog. All example texts can be found at jTrolog’s homepage (Ørstavik 2008), and interested readers are encouraged to consult jTrolog’s source code for more details. For details about the Prolog and Java programming languages see their specification (Gosling 2000; ISO/IEC 1995; Lindholm 1999). 2 3. An intertextual analysis of a computer program This intertextual analysis analyzes the relationship between many different program texts. The analysis revolves around a small Prolog program called “bus.pl” (figure 1) and a Prolog interpreter written in Java called jTrolog (Ørstavik 2008). As this analysis focus on the programs presented as text, readers of this analysis are not required to understand the technical functions of neither bus.pl, jTrolog, Java nor Prolog in detail. The analysis is performed in the following six steps: First, a functional description of bus.pl as a computer program is given. This description explains what bus.pl is likely to do under normal circumstances. The functional description only presents a superficial reading of the program and serves primarily as an introduction to the situational context surrounding bus.pl. Second, two direct links between bus.pl as a program text and another program text called “BasicLibrary.java” are presented. These two links illustrate how bus.pl interacts with other programs and how this interaction is mediated through intertextual links. This step presents a type of intertextual links between program texts: “direct, symbolic links”. Third, the process of running bus.pl on jTrolog is analyzed. This analysis reveals how computing machines such as jTrolog literally interprets bus.pl as a program text by linking symbols and words in some of jTrolog’s program texts with corresponding symbols and words in bus.pl. This third step presents a second type of intertextual links between program texts: “direct, literal links”. Forth, the inner workings of jTrolog are analyzed. Taking an in-depth look at jTrolog running bus.pl reveals how intertextual links stretch across several layers of texts and link a many more program texts together indirectly. Grouping many program texts together creates a large network of indirect links between different program texts spanning many levels of direct symbolic and literal links. This third type of “indirect, intertextual links” and the network they make up are instrumental in both giving program words their semantic potential, while at the same time diluting it. Fifth, the relationship between real and not-yet-real program texts is discussed. Computer programs are always written for future use. These future environments room 3 many already written, real programs, but they also anticipate to room not yet written, imaginary programs. Starting with the bus.pl program, a purely hypothetical webapplication is presented, and a forth type of “imagined, intertextual links” are presented. Sixth and last, as the number of links that directly and indirectly connect real and imagined program texts together, grows, the need to establish abstract relationships between program texts becomes compulsory. Program texts such as bus.pl and jTrolog link to each other not only through a series of direct links, but also through a set of agreed-upon, shared, and abstract conventions known as programming languages. Programming languages establish an abstract intermediary that concrete program texts such as bus.pl and jTrolog can directly comply with and link to and that indirectly link all program texts relating to it to each other. From this analysis, the characteristics of program texts and the intertextual links permeating them are discussed. This discussion concludes the intertextual analysis and illustrates how program texts function as both computer programs and texts at one and the same time. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). Figure 1: A Prolog program called “bus.pl”. 4 3.1 A functional description of bus.pl As a computer program, bus.pl’s job is to calculate how to travel by bus from one destination to another. The program works by first listing a set of direct connections between two bus stops, and these direct connections are then combined into complex travel plans. This description illustrates where and how this functionality is achieved in the program text. On line 1-8 in figure 1, the direct bus connections are formulated as a series of busfacts. Each bus-fact lists three parameters: the point of departure, the point of arrival, and the bus lines’ number. On line 10-15, two plan_travel-rules describe how several such direct connections can be joined together to form two lists. The first two parameters of the plan_travel-rules also function to name the points of departure and arrival; the third parameter functions as a list specifying previously visited bus stops, mainly for internal use; and the forth and fifth parameter describes the resulting travel plans as two lists of bus line numbers and bus stops respectively. In order to get bus.pl to start running, a query such as “plan_travel(risvollan, dragvoll, [], X, Y)” must be passed to the program. First, the program will take this query and match it with one of its two plan_travel rules. Since this query contains two separate points of departure and arrival, the plan_travel-rule on line 12 will be invoked. Then, on line 13, the invoked plan_travel-rule will first try to find a bus-fact that identifies a direct connection going from “Depart” to an unknown location “X”. Then, on line 14, the invoked rule will verify that the unknown location “X” is not already part of the travel plan. The invoked rule accomplishes this by checking that “X” is not a member of the list “Visited” (this will be described in more detail in chapter 3.2). This check ensures that the program does not go in endless circles. Lastly, on line 15, the invoked rule then calls itself recursively to find a route from the unknown location “X” to the specified destination “Arrive”. This recursive process will continue until one of the following two conditions is met: One, the unknown location “X” is the same as “Arrive”. This will trigger the plan_travel-rule on line 10 that effectively halts the program. Upon return, the last two parameters of the query will describe the resulting travel plans as a list of bus line numbers 5 and a list of bus stops. Two, all possible combinations of bus-facts have been attempted without finding a route from “Depart” to “Arrive”. The program fails. Figure 2 below shows the result of running bus.pl with the example query. On line 5 and 6, the two variables “X” and “Y” describe step by step which bus line and which bus stop that leads from “risvollan” to “dragvoll”. Be aware that the two lists describe the route in reverse order, from right to left. 1 2 3 5 6 ?- plan_travel(risvollan, dragvoll, [], X, Y). result: plan_travel(risvollan, dragvoll, [], [8, 8, 8, 5, 5, 5], [dragvoll, moholt, berg, samf, lerchendal, nardo]) X: [8, 8, 8, 5, 5, 5] Y: [dragvoll, moholt, berg, samf, lerchendal, nardo] Figure 2: The result of running a query with bus.pl. This functional analysis illustrates what the program does and how it runs under normal circumstances. A more in-depth, functional analysis can break down these processes even further and give us deeper insight into the technical concepts within and underlying it. However, the purpose of this introduction is not to describe technical process. This introduction aims to illustrate the human processes of programming. So, instead of analyzing the behavior of the program, this analysis will now shift and focus on the behavior of the program texts – the program as their human creator sees it. 3.2 An analysis of direct, symbolic links between two program texts When bus.pl joins several direct bus connections together to form a compound travel plan, it faces one logical challenge. As Prolog programs only do what they are told, bus.pl needs to be told how to avoid creating bus routes that go in circles. In fact, allowing such circles is very likely to cause the program to crash. As described above, bus.pl avoids circular travel plans by checking that new bus stops have not already been visited by stating: “not member(X, Visited)”. However, two 6 words, “not” and “member”, are not described elsewhere in bus.pl, and so another resource besides the bus.pl program text is needed to make sense of these words. When running bus.pl on jTrolog, this other resource is another program text called “BasicLibrary.java”. BasicLibrary.java describes both “not” and “member” as two Prolog rules (figure 3). The “not” rule states that if the parameter passed to not can be called successfully, no alternative solutions be made available (“!”, the Prolog cut operator), and the “not”-rule should “fail”. Otherwise the “not”-rule succeeds. The “member”-rule states that if its second parameter is a list, and that the first element in this list matches the first parameter, then it succeeds. Otherwise, if the second parameter is a list that contains two or more elements, it will remove the first element and try again on the rest of the list. When bus.pl is read together with BasicLibrary.java, the two words “not” and “member” in bus.pl can be read as references or calls to the corresponding words and rules described in BasicLibrary.java. These direct, symbolic links between the two texts implements the functionality on line 14 in bus.pl, and informs our reading of bus.pl. Figure 3 below illustrate the direct, symbolic links connecting bus.pl and BasicLibrary.java. 7 bus.pl bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). ... not(G) :- call(G),!,fail. not(_). ... member(E,[E|_]). member(E,[_|L]):- member(E,L). ... BasicLibrary.java line 621-2 and 742-3 Figure 3: Direct, symbolic links between bus.pl and BasicLibrary.java. The red, dotted lines and circles illustrate the words pointing to each other across the two texts. 3.3 A literal1 analysis of a program text A computer program cannot run on its own. To run, a program must be presented to a machine that can interpret its program text and convert it into physical or virtual functions. One such machine is jTrolog. jTrolog runs Prolog programs such as bus.pl and consists of about 50 program texts written in Java. When jTrolog runs a program such as bus.pl, it first categorizes each symbol and word in the bus.pl program text into one of four groups: syntactic markers, names, numbers, and variables (figure 4). Names, numbers, and variables are content elements whose textual value is largely preserved, while syntactic markers are essentially converted 1 Literal means according to the letter and non-figurative, to view signs and words at face value only. 8 into structural organization of the other elements and then virtually erased from the text (figure 5). This process of recognizing and converting text into an alternative representation native to the machine constitute a literal interpretation. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). Figure 4: The program text bus.pl. Syntactic markers are colored grey, variables green, numbers red, and names black. However, in order to achieve this literal interpretation, jTrolog must perform a series of small, concrete steps that kneads and grinds the text of bus.pl into an acceptable symbolic form. These small, concrete steps are made through a series of explicit, literal references between symbols and words in bus.pl and corresponding symbols and words in the jTrolog program texts. In fact, every single symbol, word, and syntactical structure in bus.pl is explicitly and literally referenced in two jTrolog program texts: Tokenizer.java and Parser.java. 9 :risvollan Depart nardo bus Arrive 8 , travel_plan Visited [] Route BusLine RouteN , bus Depart X Route BusLine not travel_plan RouteN X Arrive member [] Visited X Visited X Figure 5: Two illustrations of the transformation of syntactic markers into structures of other entities. The plan_travel rule on line 12-15 is depicted as a tree, and the bus fact on line 1 is presented as containers. Figures 6 and 7 exemplify some of these explicit, literal references between bus.pl, Tokenizer.java, and Parser.java. In figure 5, some explicit references surrounding the comma symbol (“,”) are presented. The circles and lines in the figure illustrate how the commas literally point to each other and link the three texts together. These direct, literal links are instrumental in turning the text in bus.pl into syntactic structures in jTrolog. The commas in this example separate predicate parameters as a list of objects (cf. the box-inbox structure and the grey branches in figure 5). In figure 6, some explicit references surrounding Prolog variables are presented. The figure illustrate how statements such as “Character.isUpperCase(firstChar)…” and “variableList(indexOf(…” in Tokenizer.java and Parser.java literally point to Prolog variables such as ”X” and “Visited” in bus.pl. These direct, literal links are instrumental in turning some words in bus.pl into Var objects, an internal, symbolic representation in jTrolog (cf. the green circles in figure 5). 10 11 bus.pl Parser Figure 6: A model of some intertextual connections between bus.pl, Tokenizer, and Parser that literally describe commas. if (t1.isFunctor()) { line 301-313 String functor = t1.seq; Token t = tokenizer.readToken(); //reading left par LinkedList l = new LinkedList(); do { l.add(expr(Prolog.OP_HIGH, true)); //adding argument t = tokenizer.readToken(); if (")".equals(t.seq)) //if right par, return return new Struct(functor, (Term[]) l.toArray(new Term[0])); } while (",".equals(t.seq)); //if comma, read next arg throw new InvalidTermException("Error in argument list syntax.\n" + "Token: " + t + " not expected at line " + tokenizer.lineno() + "."); } plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). plan_travel(Arrive, Arrive, Visited, [], Visited). bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). if (typea == ',') return new Token(",", Token.OPERATOR); Tokenizer line 166 12 bus.pl Parser line 293-299 Figure 7: A model of some intertextual connections between bus.pl, Tokenizer, and Parser that literally describe variable structures. if (t1.isType(Token.VARIABLE)){ int pos = variableList.indexOf(t1.seq); if (pos != -1 && t1.seq != Var.ANY) return new Var(t1.seq, pos+1); variableList.add(t1.seq); return new Var(t1.seq, variableList.size()); } plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). plan_travel(Arrive, Arrive, Visited, [], Visited). bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). Tokenizer line 178-183 // variable, atom or number if (typea == TT_WORD) { char firstChar = svala.charAt(0); // variable if (Character.isUpperCase(firstChar) || '_' == firstChar) return new Token(svala, Token.VARIABLE); These and several other explicit references between the three texts2 form a series of direct, literal intertextual links. These links fulfill the intent implied in both the bus.pl and jTrolog program texts to create a virtual body of lexical and syntactic entities between them. These direct, literal links inform our understanding of the words in bus.pl in parallel with the direct, symbolic links between texts such as bus.pl and BasicLibrary.java, and all of these direct intertextual links come together and complement each other to form an ever larger and richer textual and functional picture. 3.4 Indirect links between program texts The direct, literal links between bus.pl, Tokenizer.java, and Parser.java presents a simple, still image of the variables in bus.pl. However, as described in chapter 3.1, variables in Prolog programs such as bus.pl are not primarily static entities. Prolog variables plays an active role in running programs, and so reading only a literal interpretation of bus.pl against the jTrolog program texts only gives us a piece of the puzzle. To learn more about what variables do, their purpose, and function, we must therefore read between the lines of different texts in a wider intertextual context. In figure 7, the variable “Visited” in bus.pl is linked to both Tokenizer and Parser. First, words starting with an upper-case letter are recognized as a variable “Token” object. This interpretation is based on statements such as “Character.isUpperCase(…” and “new Token(…” on line 182-183 in the Tokenizer text. Second, each variable token is added to a list, and a new “Var” object is created using each variables position in this list. This interpretation is based on words such as “variableList.indexOf(…” and “new Var(…” on line 294-298 in the Parser text. As can be read from this description, the literal interpretation rests of variables in bus.pl relies heavily on the use of other program words such as “Token”, “isUpperCase”, “indexOf”, and “Var”. These words constitute a new set of direct, symbolic links to a new 2 Figures 5 and 6 describe only some key intertextual links surrounding commas and variables in the three texts. Furthermore, as every symbols, words, and structural organizations in bus.pl can explicitly reference several different statements in Tokenizer and Parser, a large number of intertextual links that make up the literal interpretation of bus.pl by jTrolog still remain to be presented. However, to describe all these links together in a figure or text would be extremely complex or tedious. Therefore, this analysis has chosen only to exemplify the quality of the intertextual links permeating program texts. 13 group of program texts: “Token”, “Character”, “List”, and “Var”. Tokenizer and Parser are thus part of a larger web of intertextual links, and these other links are instrumental in shaping the meaning of the links underlying the literal interpretation. Figure 8 below illustrates a network of indirect links informing our understanding of the variables in bus.pl. package jTrolog.terms; import jTrolog.errors.InvalidTermException; text /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; text /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); public final static String ANY = "_".intern(); private String name; public final int nrInStruct; private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; package jTrolog.terms; import jTrolog.errors.InvalidTermException; public final static String ANY = "_".intern(); package jTrolog.terms; import jTrolog.errors.InvalidTermException; package jTrolog.terms; import jTrolog.errors.InvalidTermException; text /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { text private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { text public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; public interface List<E> extends Collection<E> { // Query Operations List /** * Returns the number of elements in this list. If this list contains * more than <tt>Integer.MAX_VALUE</tt> elements, returns * <tt>Integer.MAX_VALUE</tt>. * * @return the number of elements in this list */ int size(); package jTrolog.parser; import java.io.Serializable; static final int ATOM = 'A'; static final int SQ_SEQUENCE = 'S'; static final int DQ_SEQUENCE = 'D'; static final int OPERATOR = 'O'; static final int FUNCTOR = 'F'; /** * Returns <tt>true</tt> if this list contains the specified element. * More formally, returns <tt>true</tt> if and only if this list contains package jTrolog.terms; import jTrolog.errors.InvalidTermException; Token /** * This class represents a token read by the prolog term tokenizer */ class Token implements Serializable { // token textual representation String seq; // token type and attribute int type; /** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */ boolean isEmpty(); static final int ATOM_OPERATOR = 'B'; static final int ATOM_FUNCTOR = 'a'; Character public final class Character extends Object implements java.io.Serializable, Comparable<Character> { /** * The minimum radix available for conversion to and from strings. * The constant value of this field is the smallest value permitted * for the radix argument in radix-conversion methods such as the * <code>digit</code> method, the <code>forDigit</code> * method, and the <code>toString</code> method of class * <code>Integer</code>. * * @see java.lang.Character#digit(char, int) * @see java.lang.Character#forDigit(int, int) * @see java.lang.Integer#toString(int, int) * @see java.lang.Integer#valueOf(java.lang.String) */ public static final int MIN_RADIX = 2; Var /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * The maximum radix available for conversion to and from strings. * The constant value of this field is the largest value permitted /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; Parser line 293-299 if (t1.isType(Token.VARIABLE)){ int pos = variableMap.indexOf(t1.seq); if (pos != -1 && t1.seq != Var.ANY) return new Var(t1.seq, pos+1); variableMap.add(t1.seq); return new Var(t1.seq, variableMap.size()); } Tokenizer line 178-183 // variable, atom or number if (typea == TT_WORD) { char firstChar = svala.charAt(0); // variable if (Character.isUpperCase(firstChar) || '_' == firstChar) return new Token(svala, Token.VARIABLE); bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). bus.pl plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). Figure 8: A network of intertextual links between bus.pl, Tokenizer, Parser, and other program texts in jTrolog and Java supporting a functional interpretation of bus.pl. The “Var.java” program text plays a pivotal role when jTrolog literally interprets and runs bus.pl. First, the Prolog variables in bus.pl such as “Visited” are set up as “Var” objects by the Parser as parts of a predicate (see figure 5). The “Var.java” program text thus functions as an internal representation of the bus.pl variables that is native to the symbolism 14 of the jTrolog program texts. And we must now look at the role of this program text when jTrolog runs bus.pl. When jTrolog solves a query, it does so by building a predicate for the query and then matching this query predicate with the predicates describing the facts and rules of its running programs. If the query matches a fact or rule predicate that in turn contains references to other rules, these rules are then converted to sub-queries and attempted solved. jTrolog stacks these queries one on top of another until they are all resolved. The program texts in which these operations are described are among other Prolog.java, Engine.java, ChoicePoint.java, and LibraryTheoryManager.java. In this process of iteratively and recursively solving queries the “Var” objects play an important role. To successfully match two predicates, the two predicates must be identical except for variables. Variables function as wild cards, and when two predicates are matched during query resolution, variables on both sides are bound to the corresponding part of the opposite predicate. This process is described in BindingsTable.java and LinkTable.java. Several other program texts in jTrolog such as Struct.java, Term.java, and GarbageCan.java, as well as program texts on the Java platform such as HashMap.java, List.java, and Iterator.java, are also involved in handling Prolog variables such as “Visited” in bus.pl within the environment described in the jTrolog program texts. As all of these texts refer in turn to several other texts, the number of texts indirectly involved in any interpretation of variables in jTrolog grows exponentially. To further complicate this image, two texts can refer to each other several times in different settings depending on the state of the running system. Since the list of questions grows for each answer, often tautologically, a complete, step by step rendering of the intertextual links informing the concept of Prolog variables in bus.pl and jTrolog thus becomes both practically and principally impossible. Figure 8 below illustrates a network of indirect, intertextual links involved in a wider interpretation of “Visited” in bus.pl. 15 package jTrolog.terms; text text package jTrolog.terms; package jTrolog.terms; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { text import jTrolog.errors.InvalidTermException; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { import jTrolog.errors.InvalidTermException; text package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); private String name; public final int nrInStruct; package jTrolog.terms; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; text ChoicePoint import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public interface List<E> extends Collection<E> { // Query Operations if (t1.isType(Token.VARIABLE)){ int pos = variableMap.indexOf(t1.seq); if (pos != -1 && t1.seq != Var.ANY) return new Var(t1.seq, pos+1); variableMap.add(t1.seq); return new Var(t1.seq, variableMap.size()); } Iterator /** * Returns the number of elements in this list. If this list contains * more than <tt>Integer.MAX_VALUE</tt> elements, returns * <tt>Integer.MAX_VALUE</tt>. * * @return the number of elements in this list */ int size(); /** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */ boolean isEmpty(); class Engine { public static final int EVAL = 0; public static final int RULE = 1; public static final int BACK = 2; public static final int TRUE = 3; public static final int TRUE_ALL = 4; public static final int FALSE = 5; Engine /** * Returns the number of elements in this list. If this list contains * more than <tt>Integer.MAX_VALUE</tt> elements, returns * <tt>Integer.MAX_VALUE</tt>. * * @return the number of elements in this list */ int size(); text private Prolog prolog; BindingsTable bt; private int stackPos; private ChoicePoint[] stack; public static final int STARTUP_STACK_SIZE = 64; private int initState; private ChoicePoint query; private int stackPos; private ChoicePoint[] stack; public static final int STARTUP_STACK_SIZE = 64; private int initState; private ChoicePoint query; Engine(Prolog manager, final Struct[] queryBody) throws Throwable { Engine(Prolog manager, final Struct[] queryBody) throws Throwable { /** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */ boolean isEmpty(); class Engine { BindingsTable public static final int EVAL = 0; public static final int RULE = 1; public static final int BACK = 2; public static final int TRUE = 3; public static final int TRUE_ALL = 4; public static final int FALSE = 5; /** * Returns <tt>true</tt> if this list contains the specified element. * More formally, returns <tt>true</tt> if and only if this list contains class Engine { GarbageCan public static final int EVAL = 0; public static final int RULE = 1; public static final int BACK = 2; public static final int TRUE = 3; public static final int TRUE_ALL = 4; public static final int FALSE = 5; private Prolog prolog; BindingsTable bt; private Prolog prolog; BindingsTable bt; private int stackPos; private ChoicePoint[] stack; public static final int STARTUP_STACK_SIZE = 64; private int initState; private ChoicePoint query; private int stackPos; private ChoicePoint[] stack; public static final int STARTUP_STACK_SIZE = 64; private int initState; private ChoicePoint query; Engine(Prolog manager, final Struct[] queryBody) throws Throwable { public interface List<E> extends Collection<E> { // Query Operations package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public static final int EVAL = 0; public static final int RULE = 1; public static final int BACK = 2; public static final int TRUE = 3; public static final int TRUE_ALL = 4; public static final int FALSE = 5; private Prolog prolog; BindingsTable bt; HashMap public interface List<E> extends Collection<E> { // Query Operations LinkTable class Engine { /** * Returns <tt>true</tt> if this list contains the specified element. * More formally, returns <tt>true</tt> if and only if this list contains List Engine(Prolog manager, final Struct[] queryBody) throws Throwable { /** * Returns the number of elements in this list. If this list contains * more than <tt>Integer.MAX_VALUE</tt> elements, returns * <tt>Integer.MAX_VALUE</tt>. * * @return the number of elements in this list */ int size(); /** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */ boolean isEmpty(); Var package jTrolog.terms; /** * Returns <tt>true</tt> if this list contains the specified element. * More formally, returns <tt>true</tt> if and only if this list contains import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; private String name; public final int nrInStruct; package jTrolog.parser; import java.io.Serializable; Token static final int ATOM = 'A'; static final int SQ_SEQUENCE = 'S'; static final int DQ_SEQUENCE = 'D'; static final int OPERATOR = 'O'; static final int FUNCTOR = 'F'; static final int ATOM_OPERATOR = 'B'; static final int ATOM_FUNCTOR = 'a'; package jTrolog.terms; public final static String ANY = "_".intern(); /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * This class represents a token read by the prolog term tokenizer */ class Token implements Serializable { // token textual representation String seq; // token type and attribute int type; Struct /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); import jTrolog.errors.InvalidTermException; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; public final static String ANY = "_".intern(); text import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { Parser package jTrolog.terms; import jTrolog.errors.InvalidTermException; Term /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { Tokenizer public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). package jTrolog.terms; text import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { bus.pl plan_travel(Arrive, Arrive, Visited, [], Visited). package jTrolog.terms; plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). import jTrolog.errors.InvalidTermException; text package jTrolog.terms; import jTrolog.errors.InvalidTermException; public final static String ANY = "_".intern(); public final static String ANY = "_".intern(); private String name; public final int nrInStruct; private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; package jTrolog.terms; text /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final class Character extends Object implements java.io.Serializable, Comparable<Character> { /** * The minimum radix available for conversion to and from strings. * The constant value of this field is the smallest value permitted * for the radix argument in radix-conversion methods such as the * <code>digit</code> method, the <code>forDigit</code> * method, and the <code>toString</code> method of class * <code>Integer</code>. * * @see java.lang.Character#digit(char, int) * @see java.lang.Character#forDigit(int, int) * @see java.lang.Integer#toString(int, int) * @see java.lang.Integer#valueOf(java.lang.String) */ public static final int MIN_RADIX = 2; /** * The maximum radix available for conversion to and from strings. * The constant value of this field is the largest value permitted package jTrolog.terms; private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; if (t1.isType(Token.VARIABLE)){ int pos = variableMap.indexOf(t1.seq); if (pos != -1 && t1.seq != Var.ANY) return new Var(t1.seq, pos+1); variableMap.add(t1.seq); return new Var(t1.seq, variableMap.size()); } // variable, atom or number if (typea == TT_WORD) { char firstChar = svala.charAt(0); // variable if (Character.isUpperCase(firstChar) || '_' == firstChar) return new Token(svala, Token.VARIABLE); Character text /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { private String name; public final int nrInStruct; text import jTrolog.errors.InvalidTermException; package jTrolog.terms; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { text import jTrolog.errors.InvalidTermException; package jTrolog.terms; text /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { Figure 8: The links and semantic spaghetti that surround the Var program text. This figure illustrates the complexity of indirect, intertextual links connecting program texts. When several program texts are put together, the direct links between them become part of a network of links that indirectly connects many more texts together. The function of a program word cannot be isolated to its direct, intertextual links, but is spread out over many such indirect links. On the one hand, the indirect links lend each other a semantic meaning as playing a role in a certain network of texts, while, on the other hand, the need to interpret words by continuously following yet another indirect link dilutes the semantic meaning of every word. 3.5 Links between real and imagined program texts bus.pl was written with the purpose of presenting a simple example of how to use jTrolog. This example was later fitted to this introduction, and so the actual motive for bus.pl’s programmer was never to write a real bus-information application. However, this example 16 works better when such a bus-information application is easily imaginable. Reading and analyzing the program text of bus.pl as if it were to be used by real people wanting a bus route in Trondheim, makes it easier to understand the functions and technical meaning of its words. The environments we imagine around programs such as bus.pl are important tools for our literal and symbolic interpretation of their program texts. As illustrated in by the example query in chapter 3.1 (figure 2), the imagined environment of use surrounding bus.pl can be written down. Once formulated, the imagined query becomes a real text (figure 9), and the imagined, future environment thus includes a imagined texts. iAll programmers envisage their programs in future use, and so in anticipation of these future settings, program words are in different ways and in varying degree composed so as to facilitate other future texts using them. The plan_travel-rules in bus.pl were for example written so as to simplify the process of formulating future queries. By making these textual adjustments before the actual query was written, bus.pl linked to an imagined text. bus.pl bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). example query plan_travel(risvollan, dragvoll, [], X, Y). Figure 9: bus.pl and an example query as two texts directly linked together. All program words in bus.pl can thus be viewed as potential anchors or pointers to words in other imaginable program texts: The travel_plan-rule can be seen as a resource in a future web application for Trondheim’s bus service; and the bus-facts can be used by another Prolog application to list bus lines for individual bus stops. And such imagined 17 links are not restricted to only new situations of use. Words in bus.pl such as “member” can be imagined linking to a program text part of a different Prolog machine running bus.pl on a mobile phone. Some of these imaginable program texts may very concretely be envisaged by the programmer. Others may appear first long after the program is written. However, regardless of how specific the foreseen future environment of bus.pl is, it is never final and closed. New texts may always be imagined surrounding bus.pl, and so the future environment around bus.pl rooms an infinite number of imagined texts and imaginable intertextual links between them. Thus, the meaning of bus.pl’s words is never fixed at the time of writing, but open and rooming evermore imaginable intertextual links. Figure 9 below illustrate both these real and imagined program texts surrounding bus.pl. bus.pl bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). example query plan_travel(risvollan, dragvoll, [], X, Y). imagined Java web application imagined Prolog application public final class Character extends Object implements java.io.Serializable, Comparable<Character> { /** * The minimum radix available for conversion to and from strings. * The constant value of this field is the smallest value permitted * for the radix argument in radix-conversion methods such as the * <code>digit</code> method, the <code>forDigit</code> * method, and the <code>toString</code> method of class * <code>Integer</code>. * * @see java.lang.Character#digit(char, int) * @see java.lang.Character#forDigit(int, int) * @see java.lang.Integer#toString(int, int) * @see java.lang.Integer#valueOf(java.lang.String) */ public static final int MIN_RADIX = 2; bus(risvollan, nardo, 8). bus(nardo, lerchendal, 8). bus(lerchendal, samf, 8). bus(samf, dronningen, 8). bus(dronningen, samf, 5). bus(samf, berg, 5). bus(berg, moholt, 5). bus(moholt, dragvoll, 5). plan_travel(Arrive, Arrive, Visited, [], Visited). plan_travel(Depart, Arrive, Visited, [BusLine | RouteN], Route) :bus(Depart, X, BusLine), not member(X, Visited), plan_travel(X, Arrive, [X | Visited], RouteN, Route). imagined text /** * The maximum radix available for conversion to and from strings. * The constant value of this field is the largest value permitted imagined text package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; package jTrolog.terms; real text package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { real text import jTrolog.errors.InvalidTermException; public final static String ANY = "_".intern(); private String name; public final int nrInStruct; public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; imagined text package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); private String name; public final int nrInStruct; package jTrolog.terms; real text import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { public final static String ANY = "_".intern(); private String name; public final int nrInStruct; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; /** * needed to implement Wrapper Objects. Do not use to stringToStructList ANY Vars */ Var() { type = Term.VAR; Figure 9: Links between bus.pl and other real and imagined program texts. 18 3.5 Links to concrete and generalized program texts The last example of relevant program texts informing our figurative concept of the “Visited” variable in bus.pl and the “Var” objects in jTrolog, that we will look at here, is the machine responsible for interpreting and running the jTrolog machine. Just as each symbol and word in the Prolog program text bus.pl is given a literal interpretation and figurative interpretation by texts in the jTrolog machine, each symbol and word in the Java program texts that jTrolog is comprised of, is literally and figuratively interpreted by program texts in a Java machine. The programs responsible for interpreting Java program texts are called the Java compiler and the Java Virtual Machine (JVM). Several different versions of the JVM are written for different operating systems, and so the JVM refers to a generalized description of a design that all these different program texts all comply to. The different operating systems, such as Windows and Linux, function in turn as machines that interpret the program texts of different JVM program texts. When bus.pl functions and creates a new, real travel plan, it does so because jTrolog functions on a JVM that in turn functions on an operating system, all the way until the most basic machines of the processor program texts written in cobber, silicone, and electro mechanics is confronted. Hence, programs resemble layers in an onion: going beneath one layer of program texts only reveals another layer of program texts, until the program texts are so small and primitive that there is nothing left. Meaning and function of program texts cannot be meaningfully deconstructed as atomic entities, but should be understood as codependent references in different, constantly renewing semantic webs. Figure 10 below illustrate the many program texts in the different machines that are directly and indirectly connected to each other. 19 package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; package jTrolog.terms; import jTrolog.errors.InvalidTermException; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; package jTrolog.terms; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; package jTrolog.terms; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { bus.pl jTrolog JVM package jTrolog.terms; import jTrolog.errors.InvalidTermException; /** * This class represents a variable term. Variables are identified by a name * (which must starts with an upper case letter) or the anonymous ('_') name. * * @see Term */ public class Var extends Term { Windows Processor Figure 10: Machines of texts like layers in an onion. These networks show how computer program words derive semantic meaning from each other as members of a web of texts and intertextual links. Program functionality is expressed as textual cross references within and between program texts: Series of literal, intertextual links nested together in long chains of more complex, indirect intertextual 20 references. These intertextual networks can be both particular and generalized intertextual context, and contain real texts already written as well as imagined texts that might be written in the future. These networks are principally open, accepting new texts at all levels that can turn the interpretation of other program texts and their words up side down. Figurative and metaphorical descriptions of these networks can never be exhaustive; such descriptions can only scratch the surface and follow only few intertextual links considered particularly relevant to a particular problem or interpretation and exclude links to and between texts considered already known or less relevant. In the next section we will look at how programmers approach these networks and how they imagine and write their programs. This section will give us an understanding and metaphorical images we can use to describe the cognitive processes programmers enter into, how they relate to each other to collaboratively construct the storm of ICT systems invading our lives and culture, and the role words, texts, and language play in this communicative, writing practice. 3.5 The characteristics of intertextual links in program texts There are three questions that arise from this literal intertextual analysis. One, do the texts reference each other concretely or do they allude to each other abstractly? Two, do the texts reference already written texts, or do they reference texts that might be written in the future? And, three, do the texts reference each other reciprocally or unilaterally? A forth question, what is the role of direct vs. indirect intertextual links? First, when an instance of jTrolog interprets and runs bus.pl, the symbols and words in the text do literally reference symbols and words in Tokenizer and Parser. There are therefore literal, intertextual references from bus.pl to Tokenizer and Parser as individual, concrete texts. However, bus.pl does not exclude other programs from giving their interpretation of it. On the contrary, bus.pl is written adhering to the Prolog programming language, and one of the main purposes of the shared textual norms of Prolog is to make bus.pl interpretable and runnable on more than one individual, concrete Prolog machine. By choosing to adhere to these norms, bus.pl alludes to other program texts that choose to conform to these norms. The words and symbols in bus.pl therefore reference both individual, concrete texts such as Tokenizer and Parser and a “generalized other” of other 21 Prolog machines and other Prolog programs texts that might run it, build on it, and even misinterpret it. Second, as a Prolog program, bus.pl can be interpreted by many other Prolog machines such as SWI or JLog. However, bus.pl can also be interpreted and extended by programs not yet written. Examples of such programs can be a new and faster Prolog machine or a new web application for Trondheim’s bus service. The words in bus.pl can therefore reference individual, concrete program texts such as Tokenizer already written or a specific web application to be written. Even the “generalized other” has no fixed time and space boundaries and room both existing and future Prolog machines and other programs. The intertextual references in bus.pl address other program texts, programmers, and users – both in the past, present, and future textual settings.3 So far, we have established that program words incorporate both future, generalized references and concrete, individual references at one and the same time. Using this perspective to examine the references from bus.pl to the previously written Tokenizer and Parser, it becomes evident that the references in bus.pl are reciprocated by the two other texts. As the words and symbols in bus.pl can be seen to reference the previously-written, individual, and concrete program texts Tokenizer and Parser, the words and symbols in Tokenizer and Parser can equally be seen as referencing a “generalized other” of existing and future Prolog program texts. The intertextual links are echoed, anchored, and reflected by all.4 5 6 3 The program text from Tokenizer and Parser are written in anticipation of program texts such as bus.pl. Program texts are both written in reference to existing program texts, but also in reference to imagined, future prolog program texts along which they can run. 4 To avoid a likely misconception, one point needs to be clarified. It is common to perceive these intertextual references as unilateral, that is, going only one way from the bus.pl and into the Tokenizer and Parser program texts which in turn only grinds the text up into machine input. But even though for example the individual, concrete references are more visible than the generalized references going from bus.pl to Tokenizer and Parser, both anchor-points in both texts include both concrete and abstract references. Although developed and written against the program texts of jTrolog, the words in bus.pl that links to the words in jTrolog can also link to other Prolog engines. Similarly, during its development, the words of Tokenizer and Parser were continuously tested against a test set consisting of several actual, concrete Prolog programs. Points of reference in neither text are therefore exclusively concrete or abstract, past- or futureoriented, but all points of reference include all these aspects at one and the same time. 5 To view the intertextual relationships between program texts such as bus.pl and jTrolog as reciprocal is a challenging perspective. If computing machines are written referencing real or imagined applications, then 22 All program words do a little of everything. 4. An analysis of writing program texts , and its simplest and most concise description becomes the source code itself Key in this presentation is how programmers connect their programs. When programmers write computer programs, they essentially compose their programs as symphonies of references to and quotes from other program texts. These other texts, real or imagined, form an environment in which the program lives. However, these texts are written by many different people, at different times and places, and with different purposes. To transcend these barriers of difference, programmers develop programming languages with words and grammars that directly facilitates references to and the arranging of quotes in program texts. The first two articles of this thesis is based on this description. Morphology and Power describe in further detail how different programming languages enable and constrain programmers writing symphonies of program words. Intertextuality elaborates on how written texts and language in general form intertexts and how intertextuality can be further studied and understood. Second, and extending the understanding of what programming languages are and do, this introduction will describe how different programming languages shape how programmers envision their programs. When programmers express their own purposes as functions of other programmers texts, not only the lexical, but also the grammatical resources made available in the programming language enable and constrain the programmers. The enabling constraints of the programming languages grammar can be understood as the implicit rules of the programs environment that come into play when programs run. But precisely because these rules constrain how programs run, they must application programs might be perceived as the egg and the machine programs as the chicken. If all applications reference real or imagined machines, then computing machines are the egg and the applications the chicken. Taken to its full conclusion, this perspective erases the concept of a “natural” technological hierarchy placing hardware processors at the top and end-user software applications at the bottom (a hierarchy usually depicted bottom-up in computer literature). 6 are responsible for making the program text into a functional computer program 23 also constrain what programs programmers can envisage running. As such programming languages can be understood as not only tools for realizing computer programs, but also as tools for thinking about - or rather with - computer programs. The thesis third article on The Forms of Time and Chronotope in computer programming builds on this description and illustrate how grammatical and literary mechanisms in ordinary languages such as ancient Greek or English can do the same. 7 The programmer formulating bus.pl chooses his words well aware of how it will relate to the Tokenizer and Parser program texts. By choosing to place letters and symbols in a certain way, the bus.pl programmer recognizes, anticipates, and manipulates the intertextual connections between bus.pl and the jTrolog program texts to achieve a certain functional-rhetorical effect. But the choice of letters and symbols in Tokenizer and Parser also recognizes, anticipates, and manipulates texts such as bus.pl. Tokenizer and Parser only make sense when they are viewed as oriented toward actual, concrete or anticipated, generalized program texts. That makes the literal references pointing from Tokenizer and Parser texts to the bus.pl text just as real and non-figurative as those pointing the other way. 7 Before I begin this article I want to share an anecdote with my readers. I was attending a conference called JavaZone in Oslo in 2006. During a session one of the presenter asked the audience a question: "do you want to see some code?" To my surprise the otherwise quiet audience immideatly responded with a resounding: "Yes!" An audience most often only reluctantly giving response to the presenters questions, clearly felt strongly about this particular question. Another anecdotal point in the same direction is the humerus, subversive saying that: "the best documentation is the code itself". Programmers are often told to document their code well, that is to write meta-text about what a function or class or other piece of code does in plain English. To document program texts in this way is troublesome in many ways: first, always writing text about text amount to twice the amount of work; second, it is not always easy to translate what a piece of program code does into a regular language; and third and not least, when a piece of code is updated, its documentation is often not. All this makes experienced programmers approach any documentation with a certain degree of distrust, often preferring to read the actual code itself rather than plain English, possibly outdated stories about what the code does and how. The point of these two anecdotes to me is that code is communication. Programmers both write and read program text code, and they often prefer to read what and how functionality the others express directly in the actual program texts themselves - directly from the horses mouth. I have further come to believe that this direct approach also is suited to beginners or newbies as they are called in the technical milieu. And so this 'tell it straight' and 'show as it is' approach will be a guiding principle in this introduction, even though it is not primarily directed at seasoned programmers. 24 Magic or not In essence jTrolog does its (auto)magical process by simply connecting every word and sign in bus.pl with a piece of its own program texts (which in turn are connected to each other and with yet other program texts). In fact, all the words and signs in bus.pl are matched at least once with a particular piece of code in jTrolog, and jTrolog has no other use of bus.pl apart from making these intertextual points of connections between itself and bus.pl. So, taking the process of interpreting and running bus.pl at face value can therefore be thought of as a simple process of identifying textual references within bus.pl, between bus.pl and jTrolog, within jTrolog and between jTrolog and other program texts in turn surrounding it. We will return to the interplay between jTrolog and its surrounding in the next chapter, but before we get to that, we will do a complete analysis of what each word and symbol in bus.pl means for jTrolog. However, how bus.pl and jTrolog can produce a result can seem an automagical process of modern computer technology. Once the correct mix of program texts, such as bus.pl and a query, are presented to the computing engine, such as jTrolog, the computer technology will produce a real result, such as an actual, hitherto unknown travel plan. The computer seems able to act by itself and based on text alone conjure up new real output such as moving images, sounds, robotic movements and simple travel plans literally at the blink of an eye. It’s magic. It might seem flimsical to talk of the process of running a computer program as auto-magical. After all, few if any actually believe the computer has any supernatural powers. But, even though little superstition surrounds computers, the process of running a computer program text and creating a computer program remains for many a black box. Not knowing how computer programs work, the computer program simply seem to appear from somewhere, do something, and, voila, fulfill (or revoke) a users wishes. Further, the 25 term magic is not reserved for superstition only; magic is also used to describe card tricks and stage shows illusions that everyone in advance knows to be technical craftsmanship and make-believe. Hence, a running computer program often appears as automatic and magical. In order to understand computer programs and the practice of writing computer programs, we need to break down the auto-magical trickery and black-box concept of computer programs. To do so this introduction will first deconstruct the program text of bus.pl and show how one program engine such as jTrolog interprets its every word and sign to conjure up a new travel plan (program text deconstruction). Second, this introduction will deconstruct one entire intertextual environment in which bus.pl might be interpreted and run (program intertext deconstruction). Third, this intertextual deconstruction will be further complicated by highlighting how program texts has its own life cycle placing them in many different intertextual environments (program text life cycle deconstruction). And forth and lastly, parallel intertextual environments and settings will be exemplified illustrating the often diverse and complex dialogical nature of program text. This four-part analysis will illustrate what program texts are and how they work (at face value). References Gosling, J., Joy, B., Steele, G., and Bracha, G. 2000. The Java Language Specification. Boston: Addison-Wesley. ISO/IEC 1995. Prolog - Part 1: General core (ISO/IEC 13211-1:1995(E)). Information technology - Programming languages. Lindholm, T., and Yellin, F. 1999. The Java Virtual Machine Specification. Boston: Addison-Wesley. Ørstavik, I. 2008. jtrolog: http://jtrolog.dev.java.net/. Project home Retrieved 20.09.2008 from 26 i It is the limits of what text we can foresee surrounding our program texts, which limit our imagination of future programs. The meaning of the bus-facts and plan_travel-rules in bus.pl is therefore dependent on us imagining and seeing bus.pl in an intertextual program context of use, and the program texts and setting that surrounds them informs our understanding of words such as “plan_travel” and “bus”. 27