Skip navigation

Monthly Archives: May 2006

We celebrated the "birth" of CHAT at a party yesterday: it involved a cake, singing, sliding on water (not ice this time).  Officiating were Glenn, Bettina, Ira, and me.  Appropriate to the theme of "birth," I had invited only those CHAT members and affiliates with children young enough to be infatuated with a water slide.  Unfortunately, that meant that we were without poets and narrativists.  A video of the event marking CHAT's birth is coming.

All the skating and sliding suggests that there exists an as yet unarticulated "rule" for CHATting, that it must somehow involve speed, glide, fundamental elements, and happiness.  Intellectual propulsion will feel effortless but will in fact involve a very skillful manipulation of surface friction.  Have I just described a MMORPG, and could a CHAT tool, or in fact our blog, work as a MMORPG?

We discussed widening the scope of collaborators, trying to get natural scientists involved: any ideas about fostering collaborations of any sort, whether among HA or H,A, and NS?

After another highly successful skating CHAT session (YES! you can/should/better join us) Laura and I had a meeting with particle physicist turned coder Dave W about the development of a poetry visualization tool. Laura presented her exciting vision for the tool, and Dave and I discussed how we could help Laura build it.

Dave will handle the back-end database component, and I'll try to tackle the front-end graphical stuff. The visualization will be a dynamically generated 3D plot of user selected data fields. For example, a user may select a list of poems based on a certain time period, meter structure, theme, etc. The tool will plot the results as a series of relational nodes in 3D space, with the different axes and node types representing the relevant metrics. In addition, users will be able to specify style characteristics for nodes as well as save images of the visualizations. We'll soon be shaking the grant trees for funding (ideas/cash welcome) and developing a prototype.

Inspired by Laura's skating and generative prowess, I created a little code piece in the spirit of her vis tool (ok, it will also be an example in my book.) As usual, paste the code below in Processing and run the dang thing. If the animation runs too slowly, try lowering the number of cubies (int cubies = 150;).

// Paste the code below into Processing

Cube stage; // external large cube
int cubies = 150;
Cube[]c = new Cube[cubies]; // internal little cubes
color[][]quadBG = new color[cubies][6];

// controls cubie's movement
float[]x = new float[cubies];
float[]y = new float[cubies];
float[]z = new float[cubies];
float[]xSpeed = new float[cubies];
float[]ySpeed = new float[cubies];
float[]zSpeed = new float[cubies];

// controls cubie's rotation
float[]xRot = new float[cubies];
float[]yRot = new float[cubies];
float[]zRot = new float[cubies];

// size of external cube
float bounds = 300;

void setup(){
  size(400, 400, P3D);
  framerate(30);
  for (int i=0; i<cubies; i++){
    // each cube face has a random color component
    float colorShift = random(-75, 75);
    quadBG[i][0] = color(175+colorShift, 30, 30);
    quadBG[i][1] = color(30, 175+colorShift, 30);
    quadBG[i][2] = color(30, 30, 175+colorShift);
    quadBG[i][3] = color(175+colorShift, 175+colorShift, 30);
    quadBG[i][4] = color(175+colorShift, 30, 175+colorShift);
    quadBG[i][5] = color(175+colorShift, 87+colorShift, 30);

    // cubies are randomly sized
    float cubieSize = random(5, 10);
    c[i] =  new Cube(cubieSize, cubieSize, cubieSize);

    //initialize cubie's position, speed and rotation
    x[i] = 0;
    y[i] = 0;
    z[i] = 0;

    xSpeed[i] = random(-2, 2);
    ySpeed[i] = random(-2, 2);
    zSpeed[i] = random(-2, 2);

    xRot[i] = random(40, 100);
    yRot[i] = random(40, 100);
    zRot[i] = random(40, 100);
  }
  // instantiate external large cube
  stage =  new Cube(300, 300, 300);
}

void draw(){
  background(50);
  // center in display window
  translate(width/2, height/2, -130);
  // outer transparent cube
  noFill();
  // rotate everything, including external large cube
  rotateX(frameCount*PI/225);
  rotateY(frameCount*PI/250);
  rotateZ(frameCount*PI/275);
  stroke(255);
  // draw external large cube
  stage.create();
 
  //move/rotate cubies
  for (int i=0; i<cubies; i++){
    pushMatrix();
    translate(x[i], y[i], z[i]);
    rotateX(frameCount*PI/xRot[i]);
    rotateY(frameCount*PI/yRot[i]);
    rotateX(frameCount*PI/zRot[i]);
    noStroke();
    c[i].create(quadBG[i]);
    x[i]+=xSpeed[i];
    y[i]+=ySpeed[i];
    z[i]+=zSpeed[i];
    popMatrix();

    // draw lines connecting cubies
    stroke(35);
    if (i< cubies-1){
      line(x[i], y[i], z[i], x[i+1], y[i+1], z[i+1]);
    }

    // check wall collisions
    if (x[i]>bounds/2 || x[i]<-bounds/2){
      xSpeed[i]*=-1;
    }
    if (y[i]>bounds/2 || y[i]<-bounds/2){
      ySpeed[i]*=-1;
    }
    if (z[i]>bounds/2 || z[i]<-bounds/2){
      zSpeed[i]*=-1;
    }
  }

}

/*
Extremely simple  class to
 hold each 3D vertex
 */
class Point3D{

  float x, y, z;

  // constructors
  Point3D(){
  }

  Point3D(float x, float y, float z){
    this.x = x;
    this.y = y;
    this.z = z;
  }
}

/* custom Cube class
slightly cooler than Processing's
box() function */
class Cube{
  Point3D[] vertices = new Point3D[24];
  float w, h, d;

  //constructor
  Cube(float w, float h, float d){
    this.w = w;
    this.h = h;
    this.d = d;

    // cube composed of 6 quads
    //front
    vertices[0] = new Point3D(-w/2,-h/2,d/2);
    vertices[1] = new Point3D(w/2,-h/2,d/2);
    vertices[2] = new Point3D(w/2,h/2,d/2);
    vertices[3] = new Point3D(-w/2,h/2,d/2);
    //left
    vertices[4] = new Point3D(-w/2,-h/2,d/2);
    vertices[5] = new Point3D(-w/2,-h/2,-d/2);
    vertices[6] = new Point3D(-w/2,h/2,-d/2);
    vertices[7] = new Point3D(-w/2,h/2,d/2);
    //right
    vertices[8] = new Point3D(w/2,-h/2,d/2);
    vertices[9] = new Point3D(w/2,-h/2,-d/2);
    vertices[10] = new Point3D(w/2,h/2,-d/2);
    vertices[11] = new Point3D(w/2,h/2,d/2);
    //back
    vertices[12] = new Point3D(-w/2,-h/2,-d/2);
    vertices[13] = new Point3D(w/2,-h/2,-d/2);
    vertices[14] = new Point3D(w/2,h/2,-d/2);
    vertices[15] = new Point3D(-w/2,h/2,-d/2);
    //top
    vertices[16] = new Point3D(-w/2,-h/2,d/2);
    vertices[17] = new Point3D(-w/2,-h/2,-d/2);
    vertices[18] = new Point3D(w/2,-h/2,-d/2);
    vertices[19] = new Point3D(w/2,-h/2,d/2);
    //bottom
    vertices[20] = new Point3D(-w/2,h/2,d/2);
    vertices[21] = new Point3D(-w/2,h/2,-d/2);
    vertices[22] = new Point3D(w/2,h/2,-d/2);
    vertices[23] = new Point3D(w/2,h/2,d/2);
  }
  void create(){
    // draw cube
    for (int i=0; i<6; i++){
      beginShape(QUADS);
      for (int j=0; j<4; j++){
        vertex(vertices[j+4*i].x, vertices[j+4*i].y, vertices[j+4*i].z);
      }
      endShape();
    }
  }
  void create(color[]quadBG){
    // draw cube
    for (int i=0; i<6; i++){
      fill(quadBG[i]);
      beginShape(QUADS);
      for (int j=0; j<4; j++){
        vertex(vertices[j+4*i].x, vertices[j+4*i].y, vertices[j+4*i].z);
      }
      endShape();
    }
  }
}

Engaged in our weekly frictionless dialogue, Laura helped me to see just how utterly confused I am, all while performing greatly improving cross-overs. Fortunately, the elliptical frozen surface kept us from getting too lost. We tripped over art, text, code, beauty, kitsch, courage–freezing but not once hitting our asses on the ice.

The (pretty bad) poem below will execute in Processing. I tried (with my very limited capabilities) to illustrate an example of what I'm calling "supertext", where the source code is semantically coded and also executable. I'd be very happy to collaborate with some–more literate person than myself–on this. I could probably sling the code and conceptualize some visuals, if you could handle the wordsmithing.

// paste everything below into Processing and hit the run arrow or (OSX: cmd + r WIN: cntrl + r)

/* hunger
Ira Greenberg
original "puff" code October 22, 2005
revised "hunger" May 23, 2006
*/

// head of the beast
float heaving;
float ascension;
float anxiety = .7;
float hope = .9;
int darkness = 0;
int heavens;
int dirt;

// body of the beast
int flesh = 2000;
float[]guts= new float[flesh];
float[]blood= new float[flesh];
float[]girth = new float[flesh];
float[]heft = new float[flesh];
float[]fate = new float[flesh];
float[]compulsivity = new float[flesh];
float[]tenderness = new float[flesh];
color[]phlegm = new color[flesh];

void setup(){
size(400, 400);
heavens = width;
dirt = height;
background(255);
noStroke();
// begin in the center
heaving = heavens/2;
ascension = dirt/2;

//fill body
for (int i=0; i< flesh; i++){ girth[i] = random(-7, 7); heft[i] = random(-4, 4); compulsivity[i]= random(-9, 9); tenderness[i] = random(16, 40); phlegm[i] = color(255, 50+random(-70, 70), 30, 3); } framerate(30); }

void draw(){
background(darkness);

// purpose
for (int i =0; i< flesh; i++){
fill(phlegm[i]);
if (i==0){
guts[i] = heaving+sin(radians(fate[i]))*girth[i];
blood[i] = ascension+cos(radians(fate[i]))*heft[i];
}
else{
guts[i] = guts[i-1]+cos(radians(fate[i]))*girth[i];
blood[i] = blood[i-1]+sin(radians(fate[i]))*heft[i];

// wrenching
if (guts[i] >= heavens-tenderness[i]/2 || guts[i] <= tenderness[i]/2){
girth[i]*=-1;
tenderness[i] = random(1, 40);
compulsivity[i]= random(-13, 13);
}
if (blood[i] >= dirt-tenderness[i]/2 || blood[i] <= tenderness[i]/2){
heft[i]*=-1;
tenderness[i] = random(1, 40);
compulsivity[i]= random(-9, 9);
}
}
// creation
ellipse(guts[i], blood[i], tenderness[i], tenderness[i]);
// divinty
fate[i]+=compulsivity[i];
}

// mind wandering
heaving+=anxiety;
ascension+=hope;

// hopes edge
if (heaving >= heavens-tenderness[0]/2 || heaving <=tenderness[0]/2){
anxiety*=-1;
}
if (ascension >= dirt-tenderness[0]/2 || ascension <= tenderness[0]/2){
hope*=-1;
}
}

Wow!!! “Phatic”, “zeugma”, “syllepsis”. Laura obviously spent her time in Ithaca much more productively than I did (too much turpentine sniffing.) And she even does her homework!

“Linguistic power comes not just from the connotative dimension but also from its performativity…performativity is unlimited, dependent upon uptake and context, but those aren’t extraneous exactly – they can be coded in the linguistic production itself…”

I’m not sure I fully understand “performativity”. My point is not that natural language is limited in its potential to describe, express, etc. Obviously rich complex worlds have been built in words. But, in comparison to mathematical language, these worlds are fuzzy (in a good way.) When we say or write anything, I don’t believe the signification can ever be fully known. However, the expression 2+2 = 4 can (perhaps) never be unknown. The former is dynamic and mutable, the latter static and immutable. I am not passing a value judgment on either of these systems. We can of course, as Laura suggested, code in more context, but as we add specificity we simply approach the infinite (Zeno’s paradox).

“While it is true that in English you can say "I love my skates" and "I love my mother," it really only seems to be the case (or is only true of syntactic rules) that the verb "love" doesn't have a declared datatype for its object.”

This is precisely what I think I was trying to say. The concept of a declared (immutable) datatype is foreign to natural language, right? We can use other explicit structures to build a context of meaning, but ultimately any datatype abstraction needs to be subordinate to a dynamic emergence; language needs elbow space. This is what I meant by “semantic expansion”. From a coding perspective Datatypes (classes), in object-oriented programming, are static constructs that enforce encapsulation and contractual communication. In a pure OOP system, everything would be an object, (based on a datatype.) “Love” would be forced to choose its type. Although, through inheritance, the possibility does also exist for “Love” to be of multiple types. Regardless though, some discrete datatype(s)/object binding is required*.

“Arthur Quinn says that ‘the simplest definition of a figure of speech is an intended deviation from ordinary usage,’ an intentional mistake, and that's what your ‘I love my skates, and I love my mother’ (I'm rewriting it to make a point) would be if they appeared in the same sentence. The sentence is a specific kind of mistake…”

A discussion on the notion of “mistake” would make another worthy post (if anyone’s sitting on the sidelines ready to jump in.) I might argue (probably very foolishly) that there are ONLY mistakes in natural language and no mistakes in mathematical language. When I taught painting (prior to selling out) I described painting as a series of near misses. I guess I’m thinking of mistake as deviation from intention. Thus every human gesture is a small (or larger) mistake. Mathematically we can prove this, referring back to Zeno, but that would be damn boring. In math, until something is proven, it remains unproven; there is no figure of speech territory. Coding does offer some mistake territory, as I tried to illustrate with my fuzzy polygon program, based on random number generation.

“Barthes's S/Z is really a program that codes Balzac's short story "Sarrasine." That text demonstrates that the program for generating the story — really the program for generating any natural sentence in all its connotative and performative grandeur — would have to be so much longer than the sentence or story itself, and I'm not sure any of it would ever be generalizable to other sentences or stories, which is why such coding would be a worthless endeavor, as was my attempt to write an XSL transform to write Wordsworth's poem "A Slumber Did My Spirit Seal."

This last point I agree with. Using code as a mimetic or transformative tool is usually more work than it’s worth. However, using code as a primary generative medium offers unique and fresh possibilities, outside of the domains of natural and mathematical languages. Because code has access to the rigid precision of mathematical language and the narrative fuzziness of natural language, it offers (I still think) possibilities for a new (whole brain) integration, especially needed at our esteemed (disciplinary biased) institutions of higher learning.

* Some languages such as Java rely on late binding, allowing objects to be bound to datatypes dynamically at runtime. This approach supports polymorphism, promoting a high level of object abstraction.

. . . first, as assigned by John.  I built a game / interactive fiction in Inform 7, and you can see the results here.

Second, Ira's assignment: I generated the triangle, the polygon, and the fuzzy polygon, which IS beautiful.  But I can't somehow get from it to language, partly because I'm stuck on some of the things you are saying about language.  I want to lay out my thinking about the differences / similarities between natural language and code, based on your posting.

Linguistic power comes not just from the connotative dimension but also from its performativity.  I say "I love you" to different people to whom it means different things, but I also do different things when I say it: it can serve a phatic function, express an obsession, enact insecurity, compensate, even wound somebody — performativity is unlimited, dependent upon uptake and context, but those aren’t extraneous exactly – they can be coded in the linguistic production itself (they are, in the hands of Jane Austen, e.g., incredibly clear).

While it is true that in English you can say "I love my skates" and "I love my mother," it really only seems to be the case (or is only true of syntactic rules) that the verb "love" doesn't have a declared datatype for its object.  Arthur Quinn says that "the simplest definition of a figure of speech is 'an intended deviation from ordinary usage," an intentional mistake, and that's what your "I love my skates, and my mother" (I'm rewriting it to make a point) would be if they appeared in the same sentence.  The sentence is a specific kind of mistake — often labeled zeugma but it's really "syllepsis," I think, and the most famous example of it is Alexander Pope's line about Belinda who is in danger: Belinda may either "stain her honour, or her new brocade."  That mistake is funny because it violates rules of decorum (I'm not sure whether they are rules about connotation or rules about performance).  The performative effect, however, is to make us think about Belinda — she is clearly a ninny, someone for whom staining a dress and losing her chastity are acts of the same magnitude.  And your sentence "I love my skates, and my mother" similarly tells us something about you, which you of course recognize with the parentheses and the wink!  Rules can be written to express the performative effect: you could, I sincerely believe, make a Jane Austen game (a game about psychological realism).  If "skates" were entered into the game coded "thing [datatype] lovedObject [variableName]" while "Mom" were coded "person lovedObject," your program wouldn't ever substitute skates for Mom, or would do so only if you called function "syllepsis."  Language is only baggier than code if you don't take into account all that it is doing at any given moment, all of which can be coded.  Barthes's S/Z is really a program that codes Balzac's short story "Sarrasine."  That text demonstrates that the program for generating the story — really the program for generating any natural sentence in all its connotative and performative grandeur — would have to be so much longer than the sentence or story itself, and I'm not sure any of it would ever be generalizable to other sentences or stories, which is why such coding would be a worthless endeavor, as was my attempt to write an XSL transform to write Wordsworth's poem "A Slumber Did My Spirit Seal."

In my last comment I suggested that code, as a language system, may offer greater possibility for logic/narrative integration than might be possible in a “purer” system, such as natural or mathematical language. I guess I should probably expand upon this reckless and highly undisciplined conjecture.

I’ll begin with the very true statement:
“I love to go ice skating”

Permuting the word order some, we get:

“To go Ice skating I love”
“Ice skating I love to go”
“Love to go I ice skating”
“Love ice skating to go I”
“Ice skating to go I love”

Somehow the literal meaning of the original statement seems to remain fairly stable in the permuted variations (even without the aid of explicit syntax.) There are of course subtle shifts in expressive/poetic (connotative) meaning, which I‘ll leave for others to explain. Natural language seems especially suited to this type of fuzziness, allowing for amazing structural variations, without the (complete) loss of literal meaning. In mathematics, some similar flexibility exists, specifically through the commutative property:

45 + 65 + 193 + 200 = 503
65 + 45 + 200 + 193 = 503
200 + 193 + 65 + 43 = 503

50 x 20 x 2 = 2000
20 x 2 x 50 = 2000
2 x 50 x 20 = 2000

Using only the addition or multiplication operators in an expression, operand order doesn’t alter the evaluated value; nor does it impact expressive value. Mathematical language structures were obviously not designed to connote, but rather to definitively denote. For a simple visual explanation of commutativity. Beyond the commutative property of addition and multiplication, operand order usually alters an expression’s value:

50 – 20 x 2 = 10
50 x 2 – 20 = 80
(remember we evaluate multiplication before addition.)

In most instances, changes to operand order within expressions, as well as associative groupings (e.g. 2+3 – 6 x 5 = 30, (2+3 – 6) x 5 = -5), dramatically impact value.
(stuff between parentheses are always evaluated 1st.)

Both natural language and mathematical language are functionally efficient systems. Using the former, I can say “I love you” to my parents, grandparents, siblings, spouse, children, etc and each will take away a different meaning from the statement. The fuzziness provides utility along with the possibility for semantic expansion (my son can learn to love his pet crayfish.)
Using mathematical language, an engineer can calculate the tensile stress of an aluminum wing and communicate this value with absolute precision, without the risk of multiple interpretations–which has some benefit when you’re flying 5 miles over the Atlantic at 600 MPH.

Both natural and mathematical language systems are absolutely fundamental and at the core of, well everything; yet, they seem diametrically opposed (with regard to their defining strengths: fuzziness vs. precision.) I would also (very very politically incorrectly) argue, based on personal experiences working with both Computer Scientists/mathematicians and Artists/”Humanitists”, that the 2 language systems seem to inculcate a bias within their most ardent practitioners. I see this bias also express itself within the digital media classroom, where the majority of my students (upon entering my class) define themselves either as creative or analytical.

It is this divide, between the mutable fuzziness of natural language and the rigid precision of mathematical language, that I’d like to try to put together in a discussion on code, as a potentially integrating language system. However, as this post has already gone on far too long, I will only discuss a few procedurally based code structures. In a later post, I also plan to look at some object-oriented constructs. The code examples to follow will run in the latest version of Processing. If you haven’t checked out Processing yet I highly recommend it; although, I’m somewhat biased.

Variables:
Variables symbolically link a word (identifier) with a stored value (either directly or indirectly).
VariableName = variableValue

There are some rules defining legal identifiers, but essentially any word is valid. Besides an identifier, variables (within Processing and many other languages) are declared of a specific datatype. The datatype limits the type of data that may be associated with the identifier. Some common predefined datatypes include: int, float, String and color.
The complete declaration of a variable:
datatype VariableName = variableValue

Declared variables, as their name implies, may be assigned new values (of their declared datatype.) It is also possible, but outside of the scope of this post, to even create new custom datatypes.

Below are 5 complete and legal variable declarations, followed by a legal reassignment.
int daysOfTheWeek = 7;
int currentAge = 40;
float bodyHeat = 98.6;
String name = “ira”;
color warmth = 0xFF772A;

legal reassignment:
warmth = 0xEE0012;

In each of the statements, the initial term is the declared datatype, followed by a unique identifier, the assignment operator (“=”) and an assigned value. Each expression is terminated by a semi-colon. Variable declarations occur from right to left. So the first declaration above reads: the value 7 is assigned to the identifier daysOfTheWeek. It is a convention to capitalize the initial letter of compound identifier names-for readability.
Below are 2 new additional legal assignments, followed by 2 illegal ones.

Legal:
daysOfTheWeek = 2;
currentAge = daysOfTheWeek;

Illegal:
Warmth = bodyHeat;
currentAge = “forty”;

The initial 2 assignments meet the requirements of assigning the correct types of data to the respective variables. The 2nd statement, which might look odd to non-coders, is perfectly legal as the variable on the right (daysOfTheWeek) is 1st evaluated to 2, prior to being assigned to the variable currentAge.

The 3rd assignment statement (Warmth = bodyHeat;) is illegal because the datatypes of the variables do not match (color vs. float). Although interestingly, the assignment statement, vis-à-vis a natural level reading, seems semantically sound–body heat would generate warmth. The 4th expression is also illegal because of another datatype mismatch.

It seems that this type of assignment syntax offers interesting potential for a multi-level reading of the code, with a (natural language) narrative level (“supertext”) above a (mathematical language) logical execution level. And as was illustrated in the 3rd assignment expression above (Warmth = bodyHeat;), there can exist an interesting tension between the 2 readings.

The variable is the most basic and fundamental code structure, yet even simple assignment operations seem to illustrate an integration of natural and mathematical language systems (fuzziness and precision). Another common code structure that offers a more interesting, (or at least more fun) example of this integration is the random number generator, which we’ll look at with a visual example.

Above I tried to illustrate the fuzziness of a word like “love”, simply to emphasize the connotative range of natural language. Thus the 2 statements:
I love my ice skates
I love my mother
although structurally similar are obviously not semantically similar (or shouldn’t be ;-))

In contrast, here’s an algorithm to generate a 3-sided polygon (yes, it’s also a triangle), centered at coordinate (200, 200) with a radius of 150. Below the algorithm is some processing code that implements the algorithm. To run the code: launch Processing and paste the code into the text editor, and then press run (top left right-facing arrow) or you can use a shortcut: (OS X) command + r or (Win) control + r.

Algorithm:
Loop 3 times:
Set x = 200 + cosine(theta) * 150
Set y = 200 + sine(theta) * 150
Plot (x, y)
Increment theta by 360/3

Processing implementation:
void setup(){
 size(400, 400);
 background(255);
 float angle = 30;
 beginShape();
 for (int i =0; i<3; i++){
  float x = 200 + cos(radians(angle))*150;
  float y = 200 + sin(radians(angle))*150;
  vertex(x, y);
  angle += 360/3;
 }
 endShape();
}

The algorithm, as it is currently written, will always generate a 3-sided poly, with a radius of 150 & center point at 200, 200 (kinda boring.) Normally, we would want to functionalize this type of algorithm to at least allow any n-sided polygon to be generated and also provide parameters to control the poly’s center point and radius.

Here’s a more generalized poly algorithm:
Loop n times:
Set x = circle center along x + cosine(theta) * circle radius
Set y = circle center along y + sine(theta) * circle radius
Plot (x, y)
Increment theta by 360/n

Processing implementation:
void setup(){
 size(400, 400);
 background(255);
// generates a hexagon
 createPoly(6, 75, 200, 230);
}

void createPoly(int vertices, float radius, float centerX, float centerY) {
 float angle = 30;
 beginShape();
 for (int i=0; i<vertices; i++){
  float x = centerX + cos(radians(angle))*radius;
  float y = centerY + sin(radians(angle))*radius;
  vertex(x, y);
  angle += 360/vertices;
 }
 endShape();
}

This is an improvement, but still a far more rigid structure than our love example. Finally, we can add randomization into the function and even the function call to generate a fuzzy implementation of a precise polygon creation machine. I’ll skip the algorithm and just include a Processing implementation:

void setup(){
 size(400, 400);
 background(255);
 noStroke();
 int polys = int(random(1, 20));
 for (int i=0; i<polys; i++){
  createPoly(10, 200, width/2, height/2, 70);
  fill(random(255), 100);
 }
}

void createPoly(int vertices, float radius, float centerX, float centerY, float rand) {
 float angle = 30;
 float randvertices = random(3, vertices);
 beginShape();
 for (int i=0; i<randvertices; i++){
  float x = centerX + random(-rand, rand) + cos(radians(angle))*radius +   random(-rand, rand);
  float y = centerY + random(-rand, rand) + sin(radians(angle))*radius +   random(-rand, rand);
  vertex(x, y);
  angle += 360/randvertices;
 }
 endShape();
}

This fuzzy algorithm now begins to generate something which has certain aesthetic attributes, beyond simply being the precise output of a poly creation algorithm.

And with that I’ll put this ridiculously long post to bed.

Hey folks,

All this talk about natural language and code reminds me of the recent release of Inform 7.  Inform itself is a special purpose language specifically geared towards making interactive text games — think Zork, or if you don't know Zork consider it like a MOO, except self-contained, (usually) puzzle oriented, and finite.  At any rate, Informs 1-6 were sort of typical Perl or Python-esque scripting languages, but 7 manages to completely redo the language syntax in a more natural way.   It's worth checking out.  I often thought that if I ever did an introduction to programming languages for non-techies, I'd try to teach Inform 7.

I want to think more superficially than Ira about the relationship between code and natural language, so here is another set of undisciplined leaps (soon to be disciplined, as I slog through Logic & Language ed. by Benthem and Ter Meulen).  Casey Reas iterates the standard line about the difference between code and natural language:

Machine languages are very different from human languages: They are terse, have strict syntactial rules, and small vocabularies.  In contrast, our languages are verbose, ambiguous, and contain huge vocabularies.  ("The Language of Computers," in Creative Code, Maeda).

My own experience in both programming and writing is that, when you are first learning to write them, programs approach natural language in ambiguity and verbosity.  And the same is true of natural language: the more skilled you get, the more you can reduce verbosity and control ambiguity.  Well, you might say, if a person is an unskilled programmer, the program doesn't work.  And natural language DOES?  I remember when I first read an essay by M. H. Abrams attacking J. Hillis Miller: it was written when deconstruction first came on the scene.  Abrams countered Derrida and Miller with "language works!"  I remember thinking to myself, that doesn't really match my daily experience.  It works sometimes a lot better than others — and that's just at the level of passing information — never mind sincerity, authenticity, effectivity.

But the breakdowns in programming and natural language differ.  When your program is syntactially ill-formed, it works not at all, whereas something happens when you write bad sentences; it just may not be what you want to have happen.  Why?

Reas goes on to say that newer programming languages are "compromises" between machine and natural languages, and the XSL I use, which is very Englishy because XML-based, works all the time with ambiguous rules: everytime I run one particular set of transfroms, I get forty or fifty warnings about ambiguous rules.  Ambiguity will simply cause it to not run the same way each time.  But in natural language, ambiguity is different.  Certain kinds of ambiguity a writer wants absolutely to eliminate, the ambiguity that comes from confusion.  But other kinds are cultivated by writers, and there is one fundamental kind of ambiguity that natural languages have: no sentence ever — ever — does only one thing.  It may tell a story, but it is also a move in a game: every story told in every sentence is persuasive, seductive.  There is no grammar without motive (to borrow a title from Kenneth Burke).

The major thinkers who tried to bridge the division between logic and grammar were the logical positivists, Carnap, the Vienna Circle, and Wittgenstein was one of them.  The early (logical) Wittgenstein attempts to reduce natural language to logical propositions.  The late (grammatical) Wittgenstein adds the game element to linguistic propositions.

But if grammar differs from logic because of motive — desire for a win state — and game rules, can't code come close to natural language?  Making games is one thing you can do with it.  But really to be a natural language, it has to come from the human mouth.  So you have code that a computer takes up and does something with.  As John Simon says, the machine takes the words out of your mouth:

When I describe programming as creative writing, I am thinking beyond the short stories and poems I wrote as a freshman in English class.  The process of coming up with an idea, developing it, and finally sitting down to type it is still the same.  But I consider programming as creative writing for a different reason: When I have finished typing, it is the writing itself that starts to create.  The code becomes a working machine, and it is fascinating to see what it will do.  ("Authorship, Creativity, and Code," in Creative Code, Maeda)

Natural language is like that, too: it takes you up and invents you as you write; it is like a machine.  But at some point your own deeper motives change the rules.  Maybe code will approach natural language as soon as programs can be written that allow the user to make changes in the program.

Ira's last posting appears as a comment — I can't quite get this program to put eveyone on as writers!  But Ira's posting is too important to be hidden in the commentary, so here it is.  Ira writes,

Here’s a rather large and “undisciplined” leap.

Rather than define the blurring with disciplinary-based (and very high-level) binaries: “designer and artist, author and designer…” I’d suggest going a level lower and argue that code (the medium to manipulate electricity) blurs the line separating natural language and mathematical language. This binary seems to be the key dilimiter, dividing not only our brains but our universities and beyond. The binary also seems to subjugate other formal language systems: we define visual or aural language in terms of analytical and/or narrative structures. A work of art reflects this bifurcation-e.g. a geometric 2D pictorial structure anchors an expressive figurative narrative. Integration happens only though explicit organization. Natural language systems seem to sacrifice rigidity for mutability, while mathematical systems employ an opposite strategy.

Code has the potential to be an integrated language system, functioning both as an analytically and narratively expressive medium. So yes, I’d say Cooper may be right.