Giter Club home page Giter Club logo

match-ts's Introduction

@dkendal/match

Provides pattern matching features typically found in functional languages like Elixir/Erlang, ML, F#, etc.

Installation

yarn add @dkendal/match

The match function

The match function lets us compare a value against many patterns until we find one that matches.

import { __, match, when } from '@dkendal/match'

match(
  [1, 2, 3],
  when([4, 5, 6], () => "This clause won't match"),
  when([1, __, 3], () => 'This clause will match, __ will match any value'),
  when(__, () => 'This clause would match any value'),
)

'This clause will match, __ will match any value'

The value that was passed into match is also passed to the callback:

const x = 10

match(
  x,
  when(__, (value) => value * 10),
)
100

If none of the cases match and error is thrown:

match([1, 2, 3]
      when([1, 2], () => "this won't match as the array lengths don't agree"))
// (Error) unmatched case: [1, 2, 3]

The when function

The when function exists purely for typing. When you use it gives the callback the proper type expressed in the left-hand-side pattern:

when(
  V('checkout', {
    type: 'checkout',
    lineItems: [V('firstLineItem', { type: 'line_item', data: __ }), __.rest],
  }),
  ({ checkout, firstLineItem }) => {
    var checkout: {
      type: 'checkout'
      id: number
      lineItems: [{
        type: 'line_item'
        id: number
        data: any
      }, any[]]
    }

    var firstLineItem: {
      type: 'line_item'
      id: number
      data: any
    }
  },
)

match function continued

Array's are matched as tuples, the lengths have to be the same:

match([1, 2, 3]
      when([1, 2], () => "this won't match"),
      when([1, 2, 3], () => "this will match"))
"this will match"

The tail of a list can be matched with __.rest, or it's aliases __.tail or __.tl:

match(
  range(50, 100),
  when([50, 51, __.rest], () => 'this will match'),
)
;('this will match')

Primitive types can be matched with special operators:

const thingy: {
  data: {
    someNumber: 1
    metadata: { foobar: 'foobar' }
    someOtherProp: {}
  }
  list: [1, 2, 3]
}

match(
  thingy,
  when(
    {
      data: { someNumber: __.number, metadata: __.object },
      list: [__, __.rest],
    },
    () => 'this will match',
  ),
)
;('this will match')

You can capture variables and use them on the right hand side of match, if you use when the callback will be typed with all variable bindings:

const thingy: {
  meta: {
    type: 'contrived example',
    x: 1,
    y: 2,
  },
  data: {
    a: {
      b: {
        c: {
          d: {
            message: 'hello world'
            value: 42
          }
        }
      }
    }
  }
}

match(thingy,
      when({ meta: V('x'),
         data: { a: { b: { c: { d: { value: V('y') } } } } }
       }, (captures) => captures))
{
  x: {
    type: 'contrived example',
    x: 1,
    x: 2,
  }
  y: 42
}

Variable captures can also apply a pattern that must also match for the case.

import { match, __, V } from "pattern-matching"

const checkout = {
  object: "list",
  data: [
    {
      id: "li_1",
      object: "item",
      ...
    },
    {...},
    {...}
  ]
}
match(value,
      when( { object: 'list',
          data: V('data')([
            V('first')({ object: 'item' }),
            __.rest
          ])
        }, (captures) => captures ))

{
  data: [
    {
      id: "li_1",
      object: "item",
      ...
    },
    {...},
    {...}
  ]
  first: {
    id: "li_1",
    object: "item",
    ...
  },
}

TODOs

  • Proper type inference right-hand-side of match case
  • Exhaustive type check for match cases

match-ts's People

Contributors

dkendal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.