Chain Chain Chain

I have always been interested in tiny code–the clever solution that seems too small to work.

In the 1970s, Atari game programmers crammed games into 1 or 2k cartridges. They used tricks that would never occur to us today, like scanning through the binary code data to see if any of the code could be repurposed (perhaps with a few tweaks) to be used as graphics. For the Atari Chess game, they went scanning through the logic code to try to see if any strings of bytes looked like a rook, or a bishop.

Another trick was to write your machine language code so that it did one thing if you executed the code starting at one byte, and another thing if you jumped in at the next byte. (Remember the processor was the 6502. Instructions were either one or two bytes long. Writing code interleaved in such a way was a puzzle, but could pay off in a big way if it meant the difference between a 1k ROM and a 2k ROM game cartridge.)

As computers got more powerful, the things you could do in 1k of code got more impressive. The 1k competitions for multimedia computers like the Amiga and the Atari ST were amazing, sometimes featuring 3D objects whirling about over starfields.

(We game programmers always wondered if the guys who won these competitions could write a decent videogame. That’s how we judged whether you were a good programmer or not. I don’t think we ever found out.)

But Seriously…

Aside from the “demo scene,” there have always been more serious programmers who admired pithy one-liners. Anyone who really digs APL or Perl is a candidate.

Yeah, Mine’s Big

We rarely think about code size any more. Our code is dwarfed by the multimedia assets we pull in. Does it matter how big your JavaScript is? It does matter, because the JavaScript code is being served over and over and over, but mostly you want it to work right, and you can get so wrapped up in the nightmares of compatibility that it’s easy to ignore your code size. “I’ll just gzip it later” is the universal thought.

But, thankfully, someone still cares about code size.

This story at Ajaxian caught my interest. It’s about an entry (by coder Mathieu ‘P01’ HENRI) in a 20-line JavaScript contest, which comes from this thread over at OzoneAsylum.

If you have a modern browser that supports Canvas (Firefox, Safari, or Opera), this short program dazzles you with a growing, rotating, glowing pattern. Here is the official link to the entry…

http://www.p01.org/releases/DHTML_contests/files/20lines_hypno_trip_down_the_fractal_rug/

Chain Chain Chain

The effect is a great one, but what really got me excited was the source code. Especially this bit…

//chain a bunch of CanvasRenderingContext2D methods
for( chainThat in {set:1,switchTo:1,clearRect:1,save:1,
     translate:1,rotate:1,drawImage:1,scale:1,
     restore:1,fillRect:1,moveTo:1,lineTo:1,
     beginPath:1,closePath:1,stroke:1,fill:1,arc:1} )
{
  window.fx.CanvasRenderingContext2D[chainThat] =
    chain(window.fx.
      CanvasRenderingContext2D[chainThat]);
}

And here’s the code for the “chain” method…

//  chain( func )
//  make func chainable by making it return
//    its ReturnValue || this
  function chain( func )
  {
    return function()
    {
      return func.apply(this,arguments)||this;
    }
  }

This clever bit of metaprogramming turns a bunch of Canvas functions into functions that can be chained (also known as a cascaded). I don’t know if p01 came up with this trick, or whether he stumbled upon it somewhere else, but it’s a great idea. It lets him perform a whole series of operations in one line.

/* 15 */ fx
.logicCtx
	.set( 'globalCompositeOperation', 'source-over' )
	.clearRect( 0, 0, 256, 192 )
	.save()
	.translate( 96, 96 )
	.rotate( (now/5841%2)*Math.PI )
	.scale( 1+2*((now/1274)%1), 1+2*((now/1274)%1) )
	.drawImage( fx.fooCtx.canvas,0,0,192,192, -288,-288,576,576 )
	.drawImage( fx.fooCtx.canvas,0,0,192,192, -96 ,-96 ,192,192 )
	.drawImage( fx.fooCtx.canvas,0,0,192,192, -32 ,-32 ,64 ,64  )
	.restore()
	.set( 'globalCompositeOperation', 'copy' )
//	prepare for hypnoglow
.switchTo( fx.renderCtx )
	.set( 'globalCompositeOperation', 'source-over' )
	.clearRect( 0, 0, 192, 192 )
	.drawImage( fx.logicCtx.canvas, 0, 0 )
	.set( 'globalCompositeOperation', 'lighter' );

See the dots (the periods) that chain the methods together?

That whole bit counts as one line of JavaScript (line 15, as you can see by the comment), for the sake of this contest (it would be uglier on one physical line, but it’d work).

Users of the jQuery library are used to this chaining. It works if you return this instead of letting the default value undefined be returned.

Next time I use Canvas, I’m stealing this trick.

True story.

When I took Numerical Methods in college, our APL programs were graded based on the number of characters in the program. This was hardcore APL, on a timeshare DEC computer with dedicated APL Greek-letter keyboards and special video terminals that could display the Greek APL symbols (this was back in the days of monochrome text displays–before graphics terminals were common).

Advertisements

How Weird are JavaScript Arrays?

How weird are JavaScript arrays? Really weird.

In most programming languages that I’ve worked with, arrays and objects are two different types. An array is a pie, and an object is a cake.

JavaScript is so object-oriented that it’s difficult to draw a line between the pie and the cake. In JavaScript, arrays are cheesecake. This can be disturbing, It can make some programmers angry. I’m going to ask you to try to remain calm. If I upset you, please, just walk away.

It all starts out normally (like the first scene of a Hitchcock film). No surprises yet. Let’s look at an object and an array.

var obj={"species":"dog","name":"buster"};
var arr=["dog","buster"];
alert(obj.species); //dog
alert(arr[0]); //dog

Pretty close. The object uses braces, rather than square brackets. While the object labels its elements, the array numbers them. You use dot notation to get at the info in an object, and the square brackets (array notation) to get at the info in an array.

Now it Starts to Get Interesting

We can also get at object values with this array-like syntax:

alert(obj["species"]); //dog

Now, our object looks almost like an array.

In most languages, arrays are optimized for speed. Each element is the same type and size and can be quickly accessed. In JavaScript, arrays are so loose that there’s really no speeding them up. Each array element can hold a different type.

arr[0]='pig';
arr[1]=true;
arr[2]=[5,2,7,3];
arr[3]={'a':1,'b':2};

An array element can even hold a function (or an array of functions)!

This is massively handy, if unusual.

Sit Down, I Have Something Scary to Tell You

I’m sorry, but it’s time for me to do something that may weird you out. Look at this…

arr["state"]=0;

That’s upsetting. Arrays can do more than just hold their numbered elements, they can also act just like objects, holding named values. If you want to kick something, or yell, I don’t blame you. If you need to take a few deep breaths, I understand.

You have a choice to make. You need to get all cold, steely, and rational and decide if it makes sense to take advantage of what JavaScript offers, or if you’re better off backing off and doing things the way you’d do them in other languages. That depends on your situation. Are you the only coder who will ever see the code? If you’re working with others, you may very well blow their minds if you treat an array like an object. Or maybe you’re working with some like-minded cheesecake aficionados.

Are You Insane?

But there are some very nice things you can do with this. Having all information that’s associated with the array (maybe even the array’s methods) live inside the array can make your code easier to deal with and understand, but only if you understand that an array is a cheesecake.

If you don’t take advantage of this, but you do want to keep everything associated with the array together, you’ll use an object to wrap everything up, and the array will be part of the object. This is more clear to the traditional thinker, but it does have a cost–the overhead of all the extra symbols you’ll be typing to access things.

Here are an array and an object, both designed to hold the same things.

var arr=[],obj={};
arr.state=0;
arr[0]='dog';
arr[1]='cat';
obj.state=0;
obj.data=[];
obj.data[0]='dog';
obj.data[1]='cat';

I can make a pretty good case that the array is “better” in this case, assuming you’re a big fan of cheesecake.

True Story.

I once took a cat into the vet. It was my first time there so I had to fill out a form. One of the things they wanted to know was the pet’s species.

Crap. I dug deep into the part of my brain that was supposed to be holding on to my high school Latin, but I just couldn’t quite get it. I made a stab–felis domesticatus–no, can’t be right.

I walked up to the lady at the desk.

“Do people really know this?”

“Know what?”

“The species of their pet.”

“Yeah, usually.”

I pointed at my cat. “What’s this?”

She blinked, then answered, “It’s a cat.”

The Object Slinger

The more JavaScript code I write, the less secure I am in thinking I have a handle on the language. Just when I settle on a way of doing something, a startlingly better way occurs to me.

JavaScript as Sexy Forest Nymph

JavaScript is a language that seems to have grown up without the sun shining on it. While Java is the bleach blonde fake-boob lifeguard chick surrounded by gawkers, JavaScript is a hauntingly mysterious gal in the forest that you can nearly catch a glimpse of as you scramble through blackberries and brambles.

Everyone seems to know the proper way to program in Java. It’s the language you learn in college. It’s formal. It’s strict. It’s how your mother would want you to code.

No one really seems to be sure of the “right way” to code in JavaScript. Or, rather, there are a lot of people who are sue how to program in JavaScript, but they don’t all agree with each other. It’s still the wild west.

When people start coding in JavaScript, many complain that it’s not like Java. Looking for Java in JavaScript is looking for heartbreak. Instead, treat JavaScript as a magical version of C that allows you to stuff objects and functions into variables. Sometimes you don’t even have to stuff them into variables–-you can create them on the fly and pass them around.

Maybe if C had been more like JavaScript we never would have moved to C++.

Stuck

I remember that when I programmed in C, I’d often get into a situation where I had a function that had been returning one value and now I wanted it to return two values. I felt painted into a corner.

Sometimes I’d hack it so both values got returned together. If I knew x was in the range 0-15, and y was in the range 0-15, I’d return x*16+y and the calling function would do the math to break the values out into two pieces. In more difficult situations, I’d have to make a struct and pass a pointer to that around. Doesn’t sound like a big deal, really, but it broke the flow and made everything ugly.

In C++ or Java, you’re typically thinking about classes the whole way through. It’s a mindset where you’re not mad at having to put together a struct to hold structured data, you’re resigned to thinking in classes. OK, stop staring at the nymph and pay attention. I’m going to show you some code.

It’s Different

JavaScript is different. I don’t have to hack around like I did in C, and I don’t have to think in classes. I just return an object, and I can sling that object into existence right at the last minute, right in the return statement.

Here’s a ridiculous function that always returns an object that holds the numbers 10 and 12. A better example (and a rather common one) would be a library that does complex math. For illustration, this’ll do.

function giveMeX10Y12() {
    return {x:10,y:12};
},

The caller can easily pull the pieces apart:

obj=giveMeX10Y12();
console.log (obj.x,obj.y);

To me, this is what JavaScript programming is all about. It’s not about classes-–it’s about objects. It’s lightweight and comfortable, once you unlearn other languages and gain JavaScript chops.

Spaghetti Western

When you start programming JavaScript, you’re going to write some big plates of spaghetti. You’ll know you’re doing it badly. But learn to think in JavaScript and your code will be clean and easy to debug.