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\$
2
  • \$\begingroup\$ Can coffeescript compile to ES6? Is it compatible? \$\endgroup\$ Aug 9, 2015 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, 2015 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\$
2
  • 1
    \$\begingroup\$ It may be better if you separate each tip into a separate answer :) \$\endgroup\$
    – Beta Decay
    Aug 10, 2015 at 11:56
  • \$\begingroup\$ @BetaDecay Deal. \$\endgroup\$
    – metalim
    Aug 10, 2015 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\$
4
  • \$\begingroup\$ (61/3|0) works just as well for vanilla JS. \$\endgroup\$ Dec 24, 2015 at 21:14
  • \$\begingroup\$ @ETHproductions I've added it into the post to indicate the difference in bytesize \$\endgroup\$ Dec 25, 2015 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, 2016 at 7:50
  • \$\begingroup\$ You can also use //1 for a plain floor. \$\endgroup\$
    – Cyoce
    Apr 4, 2016 at 19:24
2
\$\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\$
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\$
1
  • 1
    \$\begingroup\$ For powers of two, this is irrelevant as 1<<x is equal to 2**x \$\endgroup\$
    – Stan Strum
    Dec 8, 2017 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\$
1
  • \$\begingroup\$ Same applies for searching strings, or detecting if character is in specific set: b = c in'|-+' \$\endgroup\$
    – metalim
    Aug 11, 2015 at 17:50
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 and acknowledge you have read our privacy policy.

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