8
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ Can coffeescript compile to ES6? Is it compatible? \$\endgroup\$ – proud haskeller Aug 9 '15 at 14:56
  • \$\begingroup\$ @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. \$\endgroup\$ – metalim Aug 9 '15 at 18:47

10 Answers 10

3
\$\begingroup\$

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()
\$\endgroup\$
  • 1
    \$\begingroup\$ It may be better if you separate each tip into a separate answer :) \$\endgroup\$ – Beta Decay Aug 10 '15 at 11:56
  • \$\begingroup\$ @BetaDecay Deal. \$\endgroup\$ – metalim Aug 10 '15 at 17:41
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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)
\$\endgroup\$
  • \$\begingroup\$ (61/3|0) works just as well for vanilla JS. \$\endgroup\$ – ETHproductions Dec 24 '15 at 21:14
  • \$\begingroup\$ @ETHproductions I've added it into the post to indicate the difference in bytesize \$\endgroup\$ – rink.attendant.6 Dec 25 '15 at 10:23
  • \$\begingroup\$ // is actually a .floor(), so it works differently for negative numbers: foo = -61//3 # -21, while foo = -61/3|0 # -20 \$\endgroup\$ – metalim Jan 28 '16 at 7:50
  • \$\begingroup\$ You can also use //1 for a plain floor. \$\endgroup\$ – Cyoce Apr 4 '16 at 19:24
1
\$\begingroup\$

Omit parentheses when possible

func1 func2 func3(a),func3 b

#instead of

func1(func2(func3(a),func3(b))
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Exponentiation operator **

Saves 9 bytes:

foo = 2**6
# foo = 64

Compared to JavaScript:

foo = Math.pow(2,6)
// foo = 64
\$\endgroup\$
  • \$\begingroup\$ For powers of two, this is irrelevant as 1<<x is equal to 2**x \$\endgroup\$ – Stan Strum Dec 8 '17 at 19:38
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Same applies for searching strings, or detecting if character is in specific set: b = c in'|-+' \$\endgroup\$ – metalim Aug 11 '15 at 17:50
1
\$\begingroup\$

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 ) )
\$\endgroup\$
0
\$\begingroup\$

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.
\$\endgroup\$
0
\$\begingroup\$

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]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.