docs: def _recursiveReduce(mapFunc, reductionFunc, scan, *iterables):
      """Generates the recursive reduction tree. Used by mapReduce."""
      if iterables:
          half = min(len(x) // 2 for x in iterables)
          data_left = [list(x)[:half] for x in iterables]
          data_right = [list(x)[half:] for x in iterables]
      else:
          data_left = data_right = [[]]
  
      # Submit the left and right parts of the reduction
      out_futures = [None, None]
      out_results = [None, None]
      for index, data in enumerate([data_left, data_right]):
          if any(len(x) <= 1 for x in data):
              out_results[index] = mapFunc(*list(zip(*data))[0])
          else:
              out_futures[index] = submit(
                  _recursiveReduce,
                  mapFunc,
                  reductionFunc,
                  scan,
                  *data
              )
  
      # Wait for the results
      for index, future in enumerate(out_futures):
          if future:
              out_results[index] = future.result()
  
      # Apply a scan if needed
      if scan:
          last_results = copy.copy(out_results)
          if type(out_results[0]) is not list:
              out_results[0] = [out_results[0]]
          else:
              last_results[0] = out_results[0][-1]
          if type(out_results[1]) is list:
              out_results[0].extend(out_results[1][:-1])
              last_results[1] = out_results[1][-1]
          out_results[0].append(reductionFunc(*last_results))
          return out_results[0]
  
      return reductionFunc(*out_results)