peek

peek

  • (fn: PeekFn) => (value: any) => value
  1. Peek at a value in a function chain without modifying it.

    const increment = n => n + 1
    const double = n => n * 2
    const toAnswer = n => 'answer: ' + n
    
    const logNum = n => console.log('n: ' + n)
    
    const result = passThrough(1, [increment, peek(logNum), double, toAnswer])
    
    console.log(result)
    // prints
    // n: 2
    // answer: 4
    const increment = (n: number) => n + 1
    const double = (n: number) => n * 2
    const toAnswer = (n: number) => 'answer: ' + n
    
    const logNum = (n: number) => console.log('n: ' + n)
    
    const result = passThrough(1, [increment, peek(logNum), double, toAnswer])
    
    console.log(result)
    // prints
    // n: 2
    // answer: 4
    
    const increment = n => n + 1
    const double = n => n * 2
    const toAnswer = n => 'answer: ' + n
    
    const logNum = n => console.log('n: ' + n)
    
    const result = passThrough(1, [
      increment,
      peek(logNum),
      double,
      toAnswer,
    ])
    
    console.log(result)
    // prints
    // n: 2
    // answer: 4
    const increment = (n: number) => n + 1
    const double = (n: number) => n * 2
    const toAnswer = (n: number) => 'answer: ' + n
    
    const logNum = (n: number) =>
      console.log('n: ' + n)
    
    const result = passThrough(1, [
      increment,
      peek(logNum),
      double,
      toAnswer,
    ])
    
    console.log(result)
    // prints
    // n: 2
    // answer: 4
    
  2. Peek's primary purpose is to help us debug chains of functions. So if you don't use compose or passThrough, then you probably don't need peek.

    Peek let's us inspect a value in the chain. In the function you give peek, you can set a debugger breakpoint, log the value, or do anything else you find helpful.

    Onto the example

    Below, we composed a function to calculate the bill. Looks like there's a bug! Let's peek at the intermediate values to see what's going on.

    Whoever wrote this code got the max cost instead of summing them. Let's replace getMaxValue with sumValues to fix the bug.

    const orders = {
      emma: [
        { name: 'chicken wrap', cost: 12 },
        { name: 'fries', cost: 4 },
      ],
      meg: [
        { name: 'salad', cost: 10 },
        { name: 'soup', cost: 5 },
      ],
    }
    
    const addSalesTax = multiplyBy(1.05)
    
    const logAfterCost = value => {
      console.log('after cost\n', value)
    }
    const logAfterMax = value => {
      console.log('after max\n', value)
    }
    
    const toBill = compose([
      mapValues(get('cost')),
      peek(logAfterCost),
      getMaxValue,
      peek(logAfterMax),
      addSalesTax,
      roundToNearest('0.01'),
    ])
    
    const calculateBills = mapValues(toBill)
    const bills = calculateBills(orders)
    console.log(bills)
    // is {
    //   emma: 12.6,
    //   meg: 10.5,
    // }
    //
    // should be {
    //   emma: 16.8,
    //   meg: 15.75,
    // }
    type Item = {
      name: string
      cost: number
    }
    type Orders = Record<string, Item[]>
    const orders: Orders = {
      emma: [
        { name: 'chicken wrap', cost: 12 },
        { name: 'fries', cost: 4 },
      ],
      meg: [
        { name: 'salad', cost: 10 },
        { name: 'soup', cost: 5 },
      ],
    }
    
    const addSalesTax = multiplyBy(1.05)
    
    const logAfterCost = (value: unknown) => {
      console.log('after cost\n', value)
    }
    const logAfterMax = (value: unknown) => {
      console.log('after max\n', value)
    }
    
    const getCost = get('cost')<Item>
    const toBill = compose([
      mapValues(getCost)<Item[]>,
      peek(logAfterCost),
      getMaxValue,
      peek(logAfterMax),
      addSalesTax,
      roundToNearest('0.01'),
    ])
    
    const calculateBills = mapValues(toBill)<Orders>
    const bills = calculateBills(orders)
    console.log(bills)
    // is {
    //   emma: 12.6,
    //   meg: 10.5,
    // }
    //
    // should be {
    //   emma: 16.8,
    //   meg: 15.75,
    // }
    
    const orders = {
      emma: [
        { name: 'chicken wrap', cost: 12 },
        { name: 'fries', cost: 4 },
      ],
      meg: [
        { name: 'salad', cost: 10 },
        { name: 'soup', cost: 5 },
      ],
    }
    
    const addSalesTax = multiplyBy(1.05)
    
    const logAfterCost = value => {
      console.log('after cost\n', value)
    }
    const logAfterMax = value => {
      console.log('after max\n', value)
    }
    
    const toBill = compose([
      mapValues(get('cost')),
      peek(logAfterCost),
      getMaxValue,
      peek(logAfterMax),
      addSalesTax,
      roundToNearest('0.01'),
    ])
    
    const calculateBills = mapValues(toBill)
    const bills = calculateBills(orders)
    console.log(bills)
    // is {
    //   emma: 12.6,
    //   meg: 10.5,
    // }
    //
    // should be {
    //   emma: 16.8,
    //   meg: 15.75,
    // }
    type Item = {
      name: string
      cost: number
    }
    type Orders = Record<string, Item[]>
    const orders: Orders = {
      emma: [
        { name: 'chicken wrap', cost: 12 },
        { name: 'fries', cost: 4 },
      ],
      meg: [
        { name: 'salad', cost: 10 },
        { name: 'soup', cost: 5 },
      ],
    }
    
    const addSalesTax = multiplyBy(1.05)
    
    const logAfterCost = (value: unknown) => {
      console.log('after cost\n', value)
    }
    const logAfterMax = (value: unknown) => {
      console.log('after max\n', value)
    }
    
    const getCost = get('cost')<Item>
    const toBill = compose([
      mapValues(getCost)<Item[]>,
      peek(logAfterCost),
      getMaxValue,
      peek(logAfterMax),
      addSalesTax,
      roundToNearest('0.01'),
    ])
    
    const calculateBills = mapValues(toBill)<Orders>
    const bills = calculateBills(orders)
    console.log(bills)
    // is {
    //   emma: 12.6,
    //   meg: 10.5,
    // }
    //
    // should be {
    //   emma: 16.8,
    //   meg: 15.75,
    // }