<commit_before>package japgolly.scalajs.benchmark

import Benchmark.SetupFn

/**
  * A benchmark. A single procedure to measure.
  *
  * @param setup Prepare the benchmark function. Setup and teardown times aren't measured.
  * @tparam P A param that alters the benchmark / data used by the benchmark.
  */
final class Benchmark[-P](val name: String, val setup: SetupFn[P]) {
  override def toString = name
}

object Benchmark {

  /**
    * A function that performs the part of the benchmark which should be timed.
    *
    * The timer starts immediately before running this and stop immediately on completion.
    */
  type Fn = () => Any

  type SetupFn[-P] = Setup[P, Fn]
  // TODO later: type SetupFn[-I] = Setup[I, Setup[Unit, Fn]]

  /**
    * Creates a benchmark that doesn't need any external data.
    */
  def apply(name: String)(f: => Any): Benchmark[Unit] =
    new Benchmark(name, Setup.unit(() => f))

  /**
    * Creates a benchmark that accepts a parameter (without needing transformation or preprocessing).
    */
  def apply[A](name: String, f: A => Any): Benchmark[A] =
    new Benchmark(name, Setup(a => () => f(a)))

  def setup[A, B](prepare: A => B): Builder[A, B] =
    new Builder[A, B](
      f => Setup { a =>
        val b = prepare(a)
        () => f(b)
      }
    )

  class Builder[A, B](g: (B => Any) => SetupFn[A]) {
    def apply(name: String)(f: B => Any): Benchmark[A] =
      new Benchmark(name, g(f))
  }
}<commit_msg>Add map to Benchmark setup fns<commit_after>package japgolly.scalajs.benchmark

import Benchmark.SetupFn

/**
  * A benchmark. A single procedure to measure.
  *
  * @param setup Prepare the benchmark function. Setup and teardown times aren't measured.
  * @tparam P A param that alters the benchmark / data used by the benchmark.
  */
final class Benchmark[-P](val name: String, val setup: SetupFn[P]) {
  override def toString = name
}

object Benchmark {

  /**
    * A function that performs the part of the benchmark which should be timed.
    *
    * The timer starts immediately before running this and stop immediately on completion.
    */
  type Fn = () => Any

  type SetupFn[-P] = Setup[P, Fn]
  // TODO later: type SetupFn[-I] = Setup[I, Setup[Unit, Fn]]

  /**
    * Creates a benchmark that doesn't need any external data.
    */
  def apply(name: String)(f: => Any): Benchmark[Unit] =
    new Benchmark(name, Setup.unit(() => f))

  /**
    * Creates a benchmark that accepts a parameter (without needing transformation or preprocessing).
    */
  def apply[A](name: String, f: A => Any): Benchmark[A] =
    new Benchmark(name, Setup(a => () => f(a)))

  def setup[A, B](prepare: A => B): Builder[A, B] =
    new Builder[A, B](prepare)

  class Builder[A, B](val prepare: A => B) {
    def apply(name: String)(f: B => Any): Benchmark[A] =
      new Benchmark(name, Setup { a =>
        val b = prepare(a)
        () => f(b)
      })
    def map[C](f: B => C): Builder[A, C] =
      new Builder(f compose prepare)
  }}
{'fraction_non_alphanumeric': 0.13836898395721925, 'fraction_numerical': 0.0, 'mean_word_length': 2.9800531914893615, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6440365', 'n_tokens_mistral': 996, 'n_tokens_neox': 944, 'n_words': 337}