Skip to content

Some Examples

Conan edited this page Oct 11, 2022 · 6 revisions

match-iz 🔥 docs

Examples:

In addition to the examples below, I've used match-iz myself in the following libraries: sift-r and viddy.

Front-end component

match(props)(
  when({ loading: defined }, <Loading />),
  when({ error: defined }, <Error {...props} />),
  when({ data: defined }, <Page {...props} />),
  otherwise(<Logout />)
)
// <Loading />
Full example
import * as matchiz from 'match-iz'

const { match, when, otherwise } = matchiz
const { spread, defined } = matchiz

function AccountPage(props) {
  const { loading, error, data } = spread(defined)

  return match(props)(
    when({ loading }, <Loading />),
    when({ error }, <Error {...props} />),
    when({ data }, <Page {...props} />),
    otherwise(<Logout />)
  )
}

What is spread()?

 

Reducer

match(action)(
  when({ type: 'add-todo', payload: pluck(isString) }, (payload) => ({
    ...state,
    todos: [...state.todos, { text: payload, completed: false }],
  })),

  otherwise(state)
)

What is pluck()?

Full example
import { match, when, otherwise, pluck as $ } from 'match-iz'

const todosReducer = (state, action) =>
  match(action)(
    when({ type: 'set-visibility-filter', payload: $() }, (visFilter) => ({
      ...state,
      visFilter,
    })),

    when({ type: 'add-todo', payload: $() }, (text) => ({
      ...state,
      todos: [...state.todos, { text, completed: false }],
    })),

    when({ type: 'toggle-todo', payload: $() }, (index) => ({
      ...state,
      todos: state.todos.map((todo, i) =>
        match(i)(
          when(index)({ ...todo, completed: !todo.completed }),
          otherwise(todo)
        )
      ),
    })),

    otherwise(state)
  )

What is pluck()?

 

Dates

match(new Date())(
  when(allOf(nthSun(-1), isMar), (dateObj) => {
    return 'Last Sunday of March: Clocks go forward'
  }),

  when(anyOf(isSat, isSun), () => {
    return 'Ladies and Gentlemen; The Weekend'
  }),

  otherwise('The clock is ticking')
)
Full example
import { match, when, otherwise, allOf, inRange } from 'match-iz'
import { nthSun, isMar, isOct, isDay } from 'match-iz/dates'

match(new Date())(
  when(allOf(nthSun(-1), isMar), (dateObj) => {
    return 'Last Sunday of March: Clocks go forward'
  }),

  when(allOf(nthSun(-1), isOct), (dateObj) => {
    return 'Last Sunday of October: Clocks go back'
  }),

  when(isDay(1), (dateObj) => {
    return 'Pinch punch, first day of the month!'
  }),

  when(isDay(inRange(30, 31)), (dateObj) => {
    return "It's probably not February..."
  }),

  otherwise('The clock is ticking')
)

 

Overloading

match(vector)(
  when({ x, y, z }, ({ x, y, z }) => Math.hypot(x, y, z)),
  when({ x, y }, ({ x, y }) => Math.hypot(x, y)),
  otherwise((vector) => vector.length)
)
// 3.14
Full example
import * as matchiz from 'match-iz'

const { match, when, otherwise } = matchiz
const { spread, defined } = matchiz

function getLength(vector) {
  const { x, y, z } = spread(defined)

  return match(vector)(
    when({ x, y, z }, ({ x, y, z }) => Math.hypot(x, y, z)),
    when({ x, y }, ({ x, y }) => Math.hypot(x, y)),
    otherwise((vector) => vector.length)
  )
}

What is spread()?

 

Matching array shape

match(['', '2', undefined])(
  when(['1', _, _], 'one'),
  when([_, '2', _, _], 'two, with four items'),
  when([_, '2', _], 'two'),
  otherwise('nope')
)
// "two"
Full example
import * as matchiz from 'match-iz'

const { match, when, otherwise } = matchiz
const { empty: _ } = matchiz

match(['', '2', undefined])(
  when(['1', _, _], 'one'),
  when([_, '2', _, _], 'two, with four items'),
  when([_, '2', _], 'two'),
  otherwise('nope')
)

 

Generators

function* gen() {
  yield 1
  yield 2
  yield 3
}

let res = match(gen())(
  // use array-matchers with iterables
  // to test emitted values
  when([3, 2, 1], 'back'),
  when([1, 2, 3], 'forward'),
  otherwise('no match')
)
// "forward"
Full example
import * as matchiz from 'match-iz'

const { match, when, otherwise, lastOf } = matchiz

function* range(start, end) {
  for (let i = start; i <= end; i++) {
    yield i
  }
}

let res = match(range(0, 100))(
  when([1, 2, 3], () => {
    return 'iterable emitted only 3 values: 1, 2, and 3'
  }),
  when(lastOf(50, 51), (captured) => {
    console.log('everything iterated over to get here:', captured)
    return captured
  }),
  otherwise('no match')
)
// [0, 1, 2, ..., 50, 51]

 

Map / Set

let john = { name: 'John Doe' }
let lily = { name: 'Lily Bush' }
let peter = { name: 'Peter Drucker' }

let userRolesMap = new Map([
  [john, 'admin'],
  [lily, 'editor'],
  [peter, 'subscriber'],
])

match(userRolesMap)(
  // Map: when({ key, value }, result/handler )
  when(
    {
      key: { name: includes('Bush') },
      value: isString,
    },
    ({ value: role }) => {
      return role
    }
  ),
  otherwise('sorry!')
)
// "editor"

let userSet = new Set([john, lily, peter])

match(userSet)(
  // Set: when( value, result/handler )
  when({ name: pluck(includes('Doe')) }, (value) => {
    return value
  }),
  otherwise('sorry!')
)
// "John Doe"
Full example
import * as matchiz from 'match-iz'

const { match, when, otherwise, includes, pluck } = matchiz

let john = { name: 'John Doe' }
let lily = { name: 'Lily Bush' }
let peter = { name: 'Peter Drucker' }

let userRolesMap = new Map([
  [john, 'admin'],
  [lily, 'editor'],
  [peter, 'subscriber'],
])

match(userRolesMap)(
  // Map: when({ key, value }, result/handler )
  when(
    {
      key: { name: includes('Bush') },
      value: isString,
    },
    ({ value: role }) => {
      return role
    }
  ),
  otherwise('sorry!')
)
// "editor"

let userSet = new Set([john, lily, peter])

match(userSet)(
  // Set: when( value, result/handler )
  when({ name: pluck(includes('Doe')) }, (value) => {
    return value
  }),
  otherwise('sorry!')
)
// "John Doe"

 

Data-last against can be useful for map/filter

lines.filter(
  against(
    when(/remove-this-one/, false),
    when(/and-this-one-too/, false),
    when(endsWith('-and-another'), false),
    otherwise(true)
  )
)
See a few more:
import { against, when, otherwise, lte } from 'match-iz'

function memoize(fn, cache = new Map()) {
  return (x) => (cache.has(x) ? cache.get(x) : cache.set(x, fn(x)).get(x))
}

// Fibonnacci

const fib = memoize(
  against(
    when(lte(0), 0),
    when(1, 1),
    otherwise((x) => fib(x - 1) + fib(x - 2))
  )
)

fib(35)

// Font sizes

const fontSize = memoize(
  against(
    when([100, 200], 'Super Thin'),
    when([300], 'Thin'),
    when([400, 500], 'Normal'),
    when([600, 700, 800], 'Bold'),
    when([900], 'Heavy'),
    otherwise('Not valid')
  )
)

;[100, 200, 300, 400, 500, 600, 700, 800, 900, 901].forEach((size) => {
  console.log(`${size} = `, fontSize(size))
})
import { against, when, otherwise } from 'match-iz'

// Sorting

numbers.sort(
  nargs(
    against(
      when(([a, b]) => a < b, -1),
      when(([a, b]) => a === b, 0),
      when(([a, b]) => a > b, 1)
    )
  )
)

function nargs() {
  return (fn) =>
    (...args) =>
      fn(args)
}