Tracks
/
jq
jq
/
Exercises
/
Recursive Functions
Recursive Functions

Recursive Functions

Learning Exercise

Introduction

Recursion

Recursive functions are functions that call themselves.

A recursive function needs to have at least one base case and at least one recursive case.

A base case returns a value without calling the function again. A recursive case calls the function again, modifying the input so that it will at some point match the base case.

Here is an example that counts the elements of an array.

def count:
  if length == 0 then
    0                       # base case
  else
    1 + (.[1:] | count)     # recursive case
  end;

([] | count),           # => 0
([11, 22, 33] | count)  # => 3

A recursive function can have many base cases and/or many recursive cases. For example the Fibonacci sequence is a recursive sequence with two base cases.

def fibonacci:
  if . == 0 then
    0
  elif . == 1 then
    1
  else
    (. - 1 | fibonacci) + (. - 2 | fibonacci)
  end;

10 | fibonacci          # => 55

Counting the number of occurrences of some given value x in a list has two recursive cases.

def count_occurrences(x):
  if length == 0 then
    0
  elif first == x then
    1 + (.[1:] | count_occurrences(x))
  else
    (.[1:] | count_occurrences(x))
  end;

[11, 22, 33, 22, 44] | count_occurrences(22)    # => 2

In practice, iterating over lists and other enumerable data structures is most often done using builtin functions, such as map and reduce, or by using streams like [.[] | select(...)]. Under the hood, some builtins are implemented using recursion.

Instructions

In this exercise you're going to implement some recursive functions.

1. Implement a function to add the numbers in an array

We'll re-implement the builtin add filter to practice recursion. The base case is that an empty array has a sum of zero.

Implement it yourself with a recursive function; don't use the builtin add.

[5, 4, 6, 10] | array_add     # => 25

2. Reverse an array

We'll re-implement the builtin reverse filter. The base case is that an empty array reversed is an empty array.

Implement it yourself with a recursive function; don't use the builtin reverse.

[5, 4, 6, 10] | array_reverse   # => [10, 6, 4, 5]

3. Map an array

We'll re-implement the builtin map filter. The function takes a filter as a parameter, run that filter for each element of the input array, and return the outputs in a new array. The base case is that an empty array maps to an empty array.

Implement it yourself with a recursive function; don't use the builtin map.

[5, 4, 6, 10] | array_map(. + 10)   # => [15, 14, 16, 20]
Edit via GitHub The link opens in a new window or tab
jq Exercism

Ready to start Recursive Functions?

Sign up to Exercism to learn and master jq with 12 concepts, 55 exercises, and real human mentoring, all for free.