# CoffeeScript - Second Impressions

Here’s a small raycaster in CoffeeScript. I wrote that just to see how it would look. (There’s also a small rant at the end, if that’s what you’re looking for.)

``````DIST = 9; Z_STEP = 0.1; X_STEP = 2; FOV = Math.PI/3

map_at = (x, y) -> [
" XX"
"   "
"X X"
][Math.round y]?[Math.round x] == "X"

move = (x, y, dist, dir) -> [Math.sin(dir) * dist + x,
Math.cos(dir) * dist + y]

cast = (x, y, dir) -> # optimizing for LOC, here...
for dist in [0...DIST] by Z_STEP
break if map_at (move x, y, dist, dir)...
dist

clear = (canvas) ->
ctx = canvas.getContext '2d'
ctx.fillStyle = "#fff"
ctx.fillRect 0, 0, canvas.width, canvas.height

draw = (canvas, col, dist) ->
dist_frac = Math.min(dist, DIST)/DIST
wall = (1-dist_frac) * canvas.height
color = Math.round dist_frac*255
ctx = canvas.getContext '2d'
ctx.fillStyle = "rgb(#{color}, #{color}, #{color})"
ctx.fillRect col, canvas.height/2 - wall/2, X_STEP, wall

render = (canvas, player) ->
clear canvas
for col in [0..canvas.width] by X_STEP
view_col = (col - canvas.width/2)
view_dir = view_col*(FOV/canvas.width)
draw canvas, col,
cast player.x, player.y, player.dir + view_dir

running = false
frame = ->
clearInterval running
cycle = new Date().getTime()/1000
render document.getElementById('canvas'),
x:   Math.sin(cycle)*6 + 1
y:   Math.cos(cycle)*6 + 1
dir: cycle + Math.PI # look into center
running = setInterval frame, 20

do frame
``````

Not bad, certainly more succinct than JavaScript, but …well - maybe I’ve been writing too much Scheme lately but I’ve grown to like having parentheses around everything. Making most of the nesting implicit may look cleaner, but it feels so brittle to me. One basically relies on operator precedence, and - somehow - that’s making me uncomfortable. (To be fair - I could have included much more parentheses in the above code, I just thought I’d try and go full-on crazy with CoffeeScript’s syntax).

But the biggest problem I have with these significant-whitespace and implicit-nesting languages is that they don’t go far enough: If I was to write something like

`````` foo = bar x,y
* factor
``````

or even

``````foo = bar x,y  * factor
``````

a human reader would probably assume it means

``````foo = bar(x,y) * factor
``````

But CoffeeScript parses the second one as

``````foo = bar(x,y*factor)
``````

and errors-out on the first one. In the same vein, this works in CoffeeScript:

``````coffee> (x for x in [0..3] when x != 2)
[ 0, 1, 3]
``````

But this doesn’t:

``````coffee> (x for x in [0..3] unless x == 2)
[ 0, 1, 2, 3 ]
``````

even though `unless` is a keyword and behaves as one would expect in most other cases.

``````coffee> x = 1 unless true is false
1
``````

I mean, one can go down the highway to hell road of “code that looks like English sentences”, but one has to go all the way, with a real natural language parser. But what all of these languages - including CoffeeScript - do is rename “&&” to “and” and replace some other symbols with “then” and “when”. So now stuff looks like English but behaves like code - including strange parse errors. How does that help anyone?

That’s what I meant when I said “90% design” in the last post - it just doesn’t fucking work all of the time, and that’s frustrating. One man’s “why would you do that?” is another man’s “basic usage”.

``````x = 1 if true      # works

if true x = 1      # doesn't

if true then x = 1 # works

if true then       # doesn't work
x = 1          # (parse error)

if true then       # "works"
x = 1              # (always sets x to 1)

if true            #
x = 1          # works

if true and true   #
x = 1          # works

if true            #
and true           # doesn't work
x = 1          # (parse error)

if true            #
and true        # doesn't work
x = 1          # (different parse error)

if true and        #
true            #
x = 1          # works

if true and        #
true           #
x = 1          # doesn't (!)

if true and        #
true          #
x = 1          # works (!!!!!)
``````

Python would have the same problem, if it wasn’t for the fact that stuff in parentheses is free-form there - but no such luxury in CoffeeScript.

Still, all-in-all I find CoffeeScript rather nice - it has quite a law-and-order syntax but the execution model is unchanged from JavaScript (i.e. nice and free). Simple things - that is, “real-world code” - seem to look better in CoffeeScript. And (big plus) it compiles into straight-forward, readable JavaScript.

It does leave many of JavaScript’s warts unfixed (I assume this is by design), but yeah, at least everything is an expression now and the scope behaves as it should.