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
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