Home

What is "declarative" code?

Declarative code stands in contrast with imperative code. With declarative code you say what you want. With imperative code you say how you want it done.

The most well-known declarative language is SQL. (Almost) everything you write in SQL is declarative code.

When you write "SELECT name FROM recipes" in a database you let the database do all the heavy lifting. You just write what you want (i.e. the name of all recipes) and not how you want it (e.g., go over row by row in the recipes table and grab the name of the recipe).

It's easy to write declarative code in SQL. But how do you write more declarative code in a more general programming language like Javascript?

Let's look at this example

// code snippet 1: Imperative code
/**
* returns the list of all recipe names given a list of recipes
*/
const get_recipe_names = (recipes) => {
	const recipe_names = []
	for(recipe of recipes){
	 recipe_names.push(recipe.name)
	}
    return recipe_names
}

In english:

  • go over each recipe in order and one-by-one in the recipes array
  • take the name of the recipe
  • add it to the end of the recipe_names array

This code can be more declarative:

// code snippet 2: more declarative code
/**
* returns the list of all recipe names given a list of recipes
*/
const get_recipe_names = recipes => recipes.map(recipe => recipe.name)

In english:

  • extract the name of each recipe in the recipes list
  • return the names in order

This second code snippet is more declarative because you don't stipulate that the recipes needs to be iterated over one by one. Why is this good?

  • More freedom: You can for example have a map implementation that runs code in parallel: it could split the recipes array in subarrays and send each one to a different CPU core
  • Cleaner code: You don't bother the reader with unhelpful implementation details (i.e. iterate over recipes one-by-one)

Bonus section

There is 1 more thing to notice in the modified code snippet: the use of map. You probably don't care about the order of the returned recipe names. Using map over-specifies because it will return the names in the same order as the recipes array. To deal with this leave a comment or return a Set instead of an array.

// code snippet 3: more declarative code
/**
* returns the list of all recipe names given a list of recipes
* Note: The order of the names does not need to match the order of the recipes list (use of map was a convenience)
*/
const get_recipe_names = recipes => new Set(recipes.map(recipe => recipe.name))

Why would you bother with this?

This prevents the callers of get_recipe_names from relying on undocumented specifications. This gives you more freedom to change the implementation later on.

PS: I chose a toy example to illustrate my point as clearly as possible. All of this is overkill for this example of course.