Pattern matching = switch++ - DEV Community

Pattern matching = switch++ – DEV Community

Photo by Parham Moieni on Unsplash

After learning about the exciting, but sadly only Stage 1 proposal for pattern-matching in JavaScript, I felt compelled to write a library that tries to, erm, match it as closely as I could:

import  match, when, otherwise  from 'match-iz'

match(haystack)(
  when(needle)(true),
  when(thread)(false),
  otherwise('bale')
)
Enter fullscreen mode

Exit fullscreen mode

Essentially, pattern-matching is if/then and switch/case with a little more declarative cowbell. 🐮 🔔

We can probe into an object:

const todosReducer = (state, action) =>
  match(action)(
    when( type: 'set-vis-filter' )
      (( visFilter ) => (
        ...state,
        visFilter
      )),

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

    otherwise(state)
  )
Enter fullscreen mode

Exit fullscreen mode

…test against predicates as well as literals:

const defined = obj => !!obj

function AccountPage(props) 
  return match(props)(
    when( error: true )(<Error ...props />),
    when( loading: true )(<Loading />),
    when( data: defined )(<Page ...props />),
    otherwise(<Logout />)
  )

Enter fullscreen mode

Exit fullscreen mode

…which is handy for dealing with server-responses:

const getJsonLength = async () =>
  match(await fetch('/json'))(
    when( status: 200 )
      (( headers:  'Content-Length': s  =  ) => 
        return `size is $s`
      ),

    when(( status ) => status >= 500)('Server error!'),
    when( status: 404 )('JSON not found'),
    when( status: gte(400) )('Flagrant error!'),

    otherwise("I didn't understand that...")
  )
Enter fullscreen mode

Exit fullscreen mode

…and match strings against regular-expressions, passing the result into the handler:

match('1 + 2')(
  when(/(?<left>d+) + (?<right>d+)/)
    (( groups:  left, right  ) =>
      add(left, right)
    ),

  when(/(?<left>d+) - (?<right>d+)/)
    (( groups:  left, right  ) =>
      subtract(left, right)
    ),

  otherwise("I couldn't parse that!")
)
// 3
Enter fullscreen mode

Exit fullscreen mode

The only thing we can’t have is else instead of otherwise. 😁

The full TC39 proposal is more far-reaching because it is inspired by the advanced pattern-matching features offered by functional languages with mature implementations.

Still, while we wait for the language feature I think match-iz (along with many similar libraries) is a nice tool for constructing some of the conditional logic we use in our JavaScript.

It’s not a substitute for well named intermediate variables of course, but I hope you can see its utility.


Source link