Course outline
Full-Stack course / JavaScript fundamentals

Range callbacks

Lab

How to fetch and submit this exercise

Once: install the tool and connect your account.

curl -fsSL https://gonomicon.com/install.sh | sh
gonomicon login

Each exercise: download it, edit the file named in the instructions, then submit.

gonomicon fetch fs-week-2/02-06-range-callbacks
cd 02-06-range-callbacks
gonomicon submit

The runner depends on the exercise: JavaScript/TypeScript/React labs run with Vitest, Python labs with pytest, and config-file labs (Docker, CI, Terraform, Nginx) are checked by parsing your file. gonomicon test runs the visible checks on your computer first; submitting also runs the hidden checks on our server.

Range callbacks

Write three small higher-order functions that work over a range of whole numbers, each one calling a callback you hand it.

Worked example

Here's a higher-order function that sums fn(n) for every whole number from from to to:

function sumResults(from, to, fn) {
  let total = 0;
  for (let n = from; n <= to; n++) {
    total += fn(n);
  }
  return total;
}

console.log(sumResults(1, 4, (n) => n * n));
console.log(sumResults(5, 3, (n) => n * n));
30
0

1*1 + 2*2 + 3*3 + 4*4 is 30. When from (5) is greater than to (3), the loop body never runs, so the total stays 0 and fn is never called.

Your task

Write function countMatching(from, to, test). It calls test(n) once for every whole number n from from to to (both included, in increasing order) and returns how many of those calls gave back something truthy.

Write function joinResults(from, to, fn, separator = ", "). It calls fn(n) once for every whole number from from to to (both included, in increasing order), turns each result into a string, and joins them with separator. An empty range (where from is greater than to) gives back "".

Write function twice(fn). It returns a new function that takes one input and applies fn to it twice - fn(fn(input)). Calling twice(fn) itself must not call fn - only calling the function it returns should.

Rules

  • When from is greater than to, countMatching returns 0 and joinResults returns "", and neither one ever calls its callback.
  • Every callback is called exactly once per whole number in the range, in increasing order - never skipped, never repeated, never called out of order.
  • countMatching's test can return any truthy or falsy value, not just true/false - treat it the way if would.
  • Use only if/else, loops, default parameters and template literals - no arrays, no array methods.

What you'll practice

Writing higher-order functions that loop over a range and call a callback exactly the right number of times, and a function that returns another function without running anything early.

Run it

gonomicon fetch fs-week-2/02-06-range-callbacks
cd 02-06-range-callbacks
gonomicon test
gonomicon submit

Hints

  1. A range from from to to is "both included" - the loop condition that visits every whole number in it is n <= to, not n < to.
  2. If from is greater than to, the loop body should never run at all - countMatching returns 0 and joinResults returns "" without ever calling the callback.
  3. twice(fn) should hand back a brand-new function, and that function is the only place fn actually gets called - calling twice(fn) itself must not run fn yet.