Default function parameter ordering

Coffeescript

Coffeescript Problem Overview


Reading through this, I came to the bit on default values for function arguments:

fill = (container, liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."

That's neat, but then I tried this:

fill = (container="mug", liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."

alert fill(liquid="juice")

and got the unexpected alert with "Filling the juice with coffee...". So then I tried this:

fill = (container="mug", liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."

alert fill(null, "juice")

and it worked. It's not pretty though. Is there a better way, or is this the idiomatic way to do this?

Coffeescript Solutions


Solution 1 - Coffeescript

fill = ({container, liquid} = {}) ->
     container ?= "mug"
     liquid ?= "coffee"
     
     "Filling the #{container} with #{liquid}..."
 
alert fill(liquid: "juice", container: "glass")
alert fill()

fill = (quantity="500 mL", {container, liquid} = {}) ->
     container ?= "mug"
     liquid ?= "coffee"
     
     "Filling the #{container} with #{quantity} of #{liquid}..."

alert fill("1L", liquid: "juice", container: "glass")
alert fill()
alert fill "1L"
alert fill "1L", liquid: "water"

Solution 2 - Coffeescript

Amir and Jeremy already have this. As they point out, container="mug" in a function's argument list is really just shorthand for container ?= "mug" in the function body.

Let me just add that when calling functions,

fill(liquid="juice")

means the same thing as in JavaScript: First, assign the value "juice" to the liquid variable; then pass liquid along to fill. CoffeeScript doesn't do anything special here, and liquid has the same scope in that situation as it would outside of the function call.

By the way, I've suggested that the default argument syntax should be made more powerful by allowing arguments to be skipped (e.g. (first, middle ?= null, last) -> would assign values to first and last if only two arguments were passed), and that the ?= syntax should be used rather than =. You might want to express support for that proposal here: issue 1091.

Solution 3 - Coffeescript

Currently, there's no way to call with named arguments. It would require knowing the arguments (names, positions, and/or default values) at the calling site, which is not always feasible in javascript/coffeescript.

Instead if you have many arguments and you want to name them and have default values, you could do something like this:

fill = (opts = {}) ->
	opts.container ?= "mug"
	opts.liquid ?= "coffee"
	"Filling the #{opts.container} with #{opts.liquid}..."

alert fill
	liquid:"juice"
	container:"cup"

alert fill
	liquid:"juice"

alert fill()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnmichaelsView Question on Stackoverflow
Solution 1 - CoffeescriptJeremyView Answer on Stackoverflow
Solution 2 - CoffeescriptTrevor BurnhamView Answer on Stackoverflow
Solution 3 - CoffeescriptAmirView Answer on Stackoverflow