W. Bradford Paley's CodeProfiles, currently on display at the Whitney's Programmed show, displays and engages with its own code. While the Programmed show, curated by Christiane Paul, connects the step-by-step instructional nature of digital art with the instructions of Conceptual Art, Paley's work is the one which is most explicitly Code Art, in that to view the piece is to see its code, and reading the code directly adds to the understanding of the work.

Paley's piece is a kind of self-performing code; individual lines of code light up the more they're executed, and three points move across it, each tracing their individual narratives through the code. One marks the writing the code, another how someone might read it, and the third how the machine executes it: we see them not just as "points" but ghostly lines and swirls, connections drawn back and forth, across the two-dimensional display of code. Those who can read Java may get more out of what is happening, but the piece is visually interesting enough for the uninitiated to get a sense of how these emanations mark time.

New Yorker Paley, born 1958, describes himself as a cognitive engineer, toolmaker, and educator, and has been coding computer graphics since 1973. His previous work was in information visualization, such as Relationships among Scientific Paradigms (viewable on his site) which sorts 800,000 scientific categories into 776 scientific paradigms, discovering relationships through citations, in a large visual space.

Paley made CodeProfiles for the Whitney's epochal 2002 online CODeDOC show, responding to a call for work from curator Christiane Paul "to write code that moves three points in space." Used to working with enormous data sets, he found limiting himself to just three points a challenge:

A month before the show I flashed on the idea that the source code itself could be the space, and it immediately followed from Christiane's goals that the three points should be the fixation point of someone reading the code, the execution point of the computer running it, and my own insertion point as I wrote it.

In curating Programed, Paul created several sections exploring different avenues of digital art, which were then grouped together into larger buckets. The "Signal, Sequence, Resolution" sections, for instance, emphasize digital art's connections to other media art. The "Rule, Instuction, Algorithm" sections build on the two art-historical lines most often credited as digital art's precursors: Rule-based Conceptual artists such as Sol LeWitt, and digital artists who draw from his practice like Casey Reas, who recreated several of his instruction-based wall drawings in code (we'll revisit this work in a future post about LeWitt's legacy), and early computer artists, some of whom are only now earning wider recognition, unlike their Conceptualist peers. Paul placed CodeProfiles in a section titled "Rule, Instruction, Algorithm: Collapsing Instruction and Form," putting Paley's work into conversation with two giants of Conceptual art, Laurence Weiner and Joseph Kosuth. All three works include text directly in the piece that are in some form self-describing, but each has a different take on that relationship.


Kosuth's Five Words in Neon reflected in Paley's CodeProfiles

Kosuth's work, like Paley's, is illuminated green text serving simultaneously as instruction and self-description. His work is much more concise: "FIVE WORDS IN GREEN NEON," presented as ... five words in green neon. This is not a product of instructions, like LeWitt's work, but a piece that serves as instructions itself, a prompt to initiate discussion or reflection by the audience (think of the better-known Kosuth work One and Three Chairs, previously used to illustrate conceptual work in the code space). It is instructional in the present tense. Kosuth made work for an audience of artists. Paley's work likewise rewards the engaged viewer who knows enough about code to work out why the three points are moving as they are, both in terms of their meaning and immediate cause at the code level. It speaks differently to the expert viewer. Paley does not consider himself primarily an artist but a coder:

I'm not really interested in self-expression; honestly am bored by most of it--and especially my own, since I already know the subject ... I'm more interested in understanding bits of the world in new, useful, re-organizing ways; and making tools that embody the perspectives of experts on their own subjects is the best way I've found to take my understanding forward. 

Those who can read Java can get a better sense of how approximated the three flows might be, by exercising close attention to the code; one must read the code, through the animations, to entirely work out what's happening and how these traces are conjured. Paley gives us well-commented code to read (with some rather amusing comments scattered about), but the program is of a size and complexity that we're at a bit of a disadvantage trying to run it in our heads -- and this is not code we can download and debug. There's a sense that the literalness of the traces might be up for question (how approximated are they?), but also that the answer lies in the code itself.

Wendy Chun in her On Sourcery, or Code as Fetish, cautions us to not to be too quick to equate written code with its execution, that "[c]ode does not always nor automatically do what it says, but does so in a crafty manner":

Software as we now know it (importantly, software was not always software) conflates word with result, logos with action. The goal of
software is to conflate an event with a written command. Software blurs the difference among human-readable code (readable because
of another program), its machine-readable interpretation, and its execution by turning the word “program” from a verb to a noun, by
turning process in time into process in space, by turning execution into inscription—or at least attempting to do so...

Paley gives us the program in both states: verb and noun simultaneously. Whether there is a gap between what it does and what it says is left to the viewer to parse. How, for instance, did the program track its own creation while it was being created? Paley leaves clues to how this was done.

I noodled on how I could capture the process of writing the code--the sequence of my insertion point--for a couple of days, without breaking the Java sandbox (seemed important to keep it all in the piece itself), and it clicked into place, as I say, staring at the ceiling that morning. I'll leave it up to you and your readers to figure out the geeky trick that let me start recording that sequence--in a way it let me start recording before I had even written the first line...

Anyway, after the concept hit me I just tore it out in a couple of weeks, then spent another couple of weeks tuning colors, shapes, rhythms, and timings. Writing code, like writing anything, is rewriting; that's one of the things I'm proudest of CodeProfiles for foregrounding: the loopy insertion point trace may be the most interesting one because of its "change something here, then go back and conform its references" nature.

For those interested in seeing how the "writing" trace works, this is a crucial piece. For the rest, you'll have to see the complete program at the Whitney, up through April 14, 2019. There are also a limited series of stills from the show, which can be found on his site

    Line[] readFile(String fileName) {  line(6);
        Vector v = new Vector<>();  line(11);
        try { line(8);
            //  open the file
            InputStream is = (new java.net.URL(fileName)).openStream();  line(146);
            BufferedReader br = new BufferedReader(new InputStreamReader(is));  line(3);

            //  read every line in it
            String s;  line(4);
            do {  line(13);
                s = br.readLine();  line(235);
                if (s != null) {  line(236);
                    //  remember the read code line and where we are in the program
                    Line l = new Line(s + " ");  line(10);
                    v.addElement(l);  line(12);
                    l.lineIndex = v.size()-1;

                    //  if there's a call to line() here remember the Line's index
                    int lineCallPos = l.s.indexOf("line(");
                    if (lineCallPos != -1) {
                        int lineCallEndPos = l.s.indexOf(")", lineCallPos);  line(55);
                        String param = l.s.substring(lineCallPos + 5, lineCallEndPos);
                        if (param != null && param.length() != 0) {
                            if (Character.isDigit(param.charAt(param.length()-1 +
                                line(217)))) {

                                //  remember if there's a call to line()
                                l.hasLineCall = true; line(71);

                                //  remember when it was written: line()'s parameter
                                codeInsertionIndex[
                                    l.lineAsWrittenIndex = Integer.parseInt(param)] =
                                    l.lineIndex;  line(54);

                                if (lastLineWritten < l.lineAsWrittenIndex)
                                    lastLineWritten = l.lineAsWrittenIndex;  line(194);
                            }
                        }
                    }
                    maxLineWidth = Math.max(maxLineWidth, l.s.length());  line(18);
                }
            } while (s != null);  line(14);
            is.close();  line(7);
        } catch (Exception e) { e.printStackTrace(); }  line(9);

        //  put all the lines we read into an array of Line objects
        Line lines[] = v.toArray(new Line[0]);  line(30);
        return line(19) == 0 ? lines : lines;
    }