Tips for golfing in CoffeeScript

8

1

What tricks do you know to make CoffeeScript code shorter?

CoffeeScript is language that compiles into JavaScript ("transpiles" into ES3, to be exact). The golden rule is "It's just JavaScript", meaning there's no runtime overhead. Most of JavaScript Tips & Tricks apply as well.

As a side-effect that also means: developers coming from JavaScript (including myself) tend to use JavaScript constructs instead of shorter CoffeeScript alternatives.

This thread focuses on tips specific to CoffeeScript.

Links to related topics:

Tips for golfing in JavaScript

Tips for Golfing in ECMAScript 6 and above

metalim

Posted 2015-08-09T09:09:55.203

Reputation: 523

Can coffeescript compile to ES6? Is it compatible? – proud haskeller – 2015-08-09T14:56:43.890

@proudhaskeller It compiles into ES3 in general, with one exception: if you yield, it compiles into ES6 generator. Otherwise it tries to be as browser-compliant as possible. – metalim – 2015-08-09T18:47:47.723

Answers

3

Use destructuring assignments, if structure elements are used often

Eg. get elements of first argument array

func = ([x,y,z])->
    [i,j] = doSomething x, y, x+y
    doSomethingElse i, j

# instead of

func = (a)->
    b = doSomething a[0], a[1], a[0]+a[1]
    doSomethingElse b[0], b[1]

This can be combined with splats

[first, rest..., last] = doSmth()

metalim

Posted 2015-08-09T09:09:55.203

Reputation: 523

1It may be better if you separate each tip into a separate answer :) – Beta Decay – 2015-08-10T11:56:06.310

@BetaDecay Deal. – metalim – 2015-08-10T17:41:31.810

2

Short-circuit evaluation in place of ternary operator

CoffeeScript does not have JavaScript's ternary operator ?, however the functionality of short-circuit evaluation can sometimes be used instead:

foo = a && b || c

# Long form:
foo = if a then b else c

Is somewhat equivalent to in JavaScript:

foo = a ? b : c

It will not work if b is (or can evaluate to) a falsy value such as 0.

rink.attendant.6

Posted 2015-08-09T09:09:55.203

Reputation: 2 776

2

Integer division operator //

Saves up to 10 bytes by avoiding the need to floor numbers when dividing.

Using the // operator:

foo = 61/3                 # foo = 20.333333333333332
foo = Math.floor 61/3      # foo = 20 (15 bytes)
foo = 61/3|0               # foo = 20 (6 bytes)
foo = 61//3                # foo = 20 (5 bytes)

Compared to JavaScript:

foo = 61/3                // foo = 20.333333333333332
foo = Math.floor(61/3)    // foo = 20 (16 bytes)
foo = 61/3|0              // foo = 20 (6 bytes)

rink.attendant.6

Posted 2015-08-09T09:09:55.203

Reputation: 2 776

(61/3|0) works just as well for vanilla JS. – ETHproductions – 2015-12-24T21:14:44.917

@ETHproductions I've added it into the post to indicate the difference in bytesize – rink.attendant.6 – 2015-12-25T10:23:31.603

// is actually a .floor(), so it works differently for negative numbers: foo = -61//3 # -21, while foo = -61/3|0 # -20 – metalim – 2016-01-28T07:50:24.773

You can also use //1 for a plain floor. – Cyoce – 2016-04-04T19:24:23.223

1

Omit parentheses when possible

func1 func2 func3(a),func3 b

#instead of

func1(func2(func3(a),func3(b))

metalim

Posted 2015-08-09T09:09:55.203

Reputation: 523

1

Not null but possibly falsy (0, NaN, "", false, etc.)

If you need to check if a variable is defined and not null, use the trailing question mark:

alert 'Hello world!'if foo?

Compiles to:

if (typeof foo !== 'undefined' && foo !== null) {
    alert('Hello world!')
}

This probably won't apply to many code golf entries but might be useful if you need to distinguish from a zero, false, empty string, or other falsy value.

rink.attendant.6

Posted 2015-08-09T09:09:55.203

Reputation: 2 776

1

Exponentiation operator **

Saves 9 bytes:

foo = 2**6
# foo = 64

Compared to JavaScript:

foo = Math.pow(2,6)
// foo = 64

rink.attendant.6

Posted 2015-08-09T09:09:55.203

Reputation: 2 776

For powers of two, this is irrelevant as 1<<x is equal to 2**x – Stan Strum – 2017-12-08T19:38:08.567

1

Searching arrays

Save approximately 8 bytes if you just want to check if an element is in an array, you can use the in operator.

y = x in['foo', 'bar', 'baz']

Compared to alternatives in JavaScript:

y = ~['foo', 'bar', 'baz'].indexOf(x)   // ES5, returns Number
y = ['foo', 'bar', 'baz'].includes(x)   // ES7, returns boolean
y = ~$.inArray(x,['foo', 'bar', 'baz']) // jQuery, returns Number

However in the rare case that you need the index of the element then this trick won't work for you.

rink.attendant.6

Posted 2015-08-09T09:09:55.203

Reputation: 2 776

Same applies for searching strings, or detecting if character is in specific set: b = c in'|-+' – metalim – 2015-08-11T17:50:53.710

1

Space is fun. Space is significant for calling functions

a=b[i]  # get i-th element of array b
a=b [i] # a = b( [i] ) # pass [i] to function b

m=n+k   # simple math
m=n +k  # m = n( +k ) # convert k to number and pass to function n
m=n -k  # m = n( -k ) # pass -k to function n
m=n + k # simple math again


a(b c)+d   # a( b( c ) ) + d
a (b c)+d  # a( b( c ) + d )
a (b c) +d # a( b( c )( +d ) )

metalim

Posted 2015-08-09T09:09:55.203

Reputation: 523

0

Use splats

obj.method a, params...

# instead of

obj.method.apply obj, [a].concat params

# especially useful with new objects

obj = new Obj a, params...

# alternative is complicated, unreadable and not shown here.

metalim

Posted 2015-08-09T09:09:55.203

Reputation: 523

0

Safe accessors: ?. and func? args...

Existential operator ? has many forms and uses. Apart from just checking if variable is set, you can access object methods and properties without prior checking if object is null:

obj.property?.method? args...

will execute obj.property.method args... only if obj.property and obj.property.method are defined and not null.

Useful if you iterate over several sparse arrays at the same time:

arr1[i]?.prop = arr2[i]?.method? args... for i in[0..99]

metalim

Posted 2015-08-09T09:09:55.203

Reputation: 523