No JavaScript → no output and no interactivity.

Pluralize — Smooth CoffeeScript

This literate program is interactive in its HTML5 form. Edit a CoffeeScript segment to try it. You can see the generated JavaScript as you modify a CoffeeScript function by typing ‘show name’ after its definition.


How do you add ’s’ to a word when there is more than one of something?

It is often seen in JavaScript with the ternary operator ?: but that is hard-coding at the expense of future maintenance and internationalization.

First some preliminaries. Let’s show the results whether we are running in a server or a web client. Something like show = if exports? then console.log else alert. And wrap the different methods in a test function so we can see if they work.

test = (func) ->
for points in [-3..3]
func points

Readable ways

The simplest readable way

test (points) ->
show "0: You got #{points} point#{if points > 1 then 's' else ''}"

Encapsulate in a function, future i18n will be easier

test (points) ->
pluralIf = (stem, cond) -> stem + (if cond then 's' else '')
show "1: You got #{points} #{pluralIf 'point', points > 1}"

Encapsulate in a function, handle negative numbers

test (points) ->
pluralUnless = (stem, cond) -> stem + (unless cond then 's' else '')
show "2: You got #{points} #{pluralUnless 'point', -2 < points < 2}"

Encapsulate in a String method, could collide with another definition

test (points) ->
String::pluralIf ?= (cond) -> this + (if cond then 's' else '')
show "3: You got #{points} #{'point'.pluralIf points > 1}"


Use the existential operator to catch the singular undefined

test (points) ->
show "4: You got #{points} point#{('s' if points > 1) ? ''}"

Convert the condition to a number and do an array lookup

test (points) ->
show "5: You got #{points} point#{['','s'][+(points > 1)]}"

Use the inverted condition to ask for a letter.

true => charAt 1 => ''false => charAt 0 => 's'

test (points) ->
show "6: You got #{points} point#{'s'.charAt points <= 1}"

Create an array whose length is determined by the condition. It consists of empty elements so join it with ’s’

test (points) ->
show "7: You got #{points} point#{Array(1+(points>1)).join 's'}"

Concatenate to an empty array, undefined does nothing

test (points) ->
show "8: You got #{points} point#{[].concat ('s' if points > 1)}"


Create an array with either ’s’ or undefined — from satyr

test (points) ->
show "9: You got #{points} point#{['s' if points > 1]}"

Formats CoffeeScript Markdown PDF HTML

License Creative Commons Attribution Share Alike by autotelicum © 2554/2011