Terça-feira, 4 de Outubro de 2011

Quiz #4 answers

Could you ever imagine it would go down to 154 ? We sure couldn't. The winning entries were both of the following form:

	with(A.getContext("2d"))new EventSource("events").onmessage=function(e){for(m in a=e.data.split(" "))fillStyle="rgb("+a[m],fillRect(m,o,1,1);o=a<"x"&&o+1}

or with some formatting

	with(A.getContext("2d"))
		new EventSource("events").onmessage = function(e) {
			for(m in a=e.data.split(" "))
				fillStyle="rgb("+a[m],fillRect(m,o,1,1);
			o=a<"x"&&o+1
		}

or a little bit better

	with(A.getContext("2d")) {
		new EventSource("events").onmessage = function(e) {
			for(m in a=e.data.split(" ")) {
				fillStyle="rgb("+a[m];
				fillRect(m,o,1,1);
			}
			o=a<"x"&&o+1
		}

It pulls a number of dirty tricks. First it uses with. Never use with. If you discovered with here and thought "wow, that's a spiffy keyword" you need to go watch every Doug Crockford talk. Twice.


Then it accesses DOM objects directly instead of going through getElementById. That's nasty but grandfathered into all browsers so it's OK. Of course, if you use strict like you should that trick would just fail but hey, this wasn't a beauty contest. One interesting thing about accessing DOM directly is Firefox throws a warning if you use A but throws an error if you say window.A. That's just one of Firefox's little quirks.


We won't even mention the non declared variables. The less about that the better. There's also the single statements without {}, that's a matter of style. Not using braces is wrong style.


Then there's the real jewel, "rgb(0,0,0". Yes, no closing ). By now the people running Chrome or Safari are saying "no fair, it doesn't work!". Which is wrong. It doesn't work but that's a bug in Chrome and Safari, according to HTML5 spec UAs are required to handle that. Or to quote the spec:
"For example, user agents are required to close all open constructs upon finding the end of a style sheet unexpectedly. Thus, when parsing the string "rgb(0,0,0" (with a missing close-parenthesis) for a color value, the close parenthesis is implied by this error handling rule, and a value is obtained (the color 'black'). However, the similar construct "rgb(0,0," (with both a missing parenthesis and a missing "blue" value) cannot be parsed, as closing the open construct does not result in a viable value."


Then there's a usual stringing together of statements with , which in this case saves a {} and finally the straight flush of dirty tricks. We looked at a<'x' and thought, that can't work. But it does. It defers a to string and helpfully Array.toString does join(''). It also uses && short-circuiting which comes all the way back from C. The second part only gets evaluated if the first part is trueish. So o becomes false if a doesn't start with an 'x' which gets coerced to 0 somewhere inside fillRect. If a begins with 'x' o becomes o+1, which is the last evaluated value.

You probably learned a lot about JavaScript looking at that piece of code. Don't ever use any of it! Except next year of course.

There were a few common failure causes too. Apart from the obvious image-doesn't-have-v-sync there were also different colour failures usually happening to people who tried to parse a full image into a large array. But on the shortest wrong answers there were basically two reasons. One was using EventSource without creating a new object which for some strange reason works on Firefox but is obviously wrong. The other, much harder to detect, was the Top Line of Fail, a single line at the top full of garbage or black and usually a missing line at the bottom. This is the classical off by one error caused usually by overoptimizing the v-sync detection.

Best answers for this quiz belong to João Neves and Flavio Martins (both at 154 chars), closely followed by David Rodrigues and António Lopes (both at 156 chars).

The current leaderboard will be posted soon.


publicado por jac às 15:45
link do post | comentar
|