Skip to content

Commit

Permalink
Add 'sum-types/caseof-eq'
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Scholtes committed Nov 11, 2016
1 parent 2d2ad7f commit a226167
Show file tree
Hide file tree
Showing 10 changed files with 2,259 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/index.js
/caseof-eq.js
9 changes: 6 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
language: node_js
node_js:
- "6"
- "4"
node_js: [4, 6]
install:
- npm install --global yarn
- yarn install
script:
- npm run test
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## 0.9.3 - 2016-11-11
### Added
- `sum-types/caseof-eq` for matching for equality.

## 0.9.2 - 2016-09-12
### Fixed
- Fixed thrown exception in Safari.
Expand Down
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ Install from NPM
~~~
npm install --save sum-types
~~~
and import the module

### `import 'sum-types'`

~~~js
import {makeSum, caseof} from 'sum-types'
~~~

### `makeSum()`
#### `makeSum()`

Creates an map of constructor functions from constructor definitions

Expand Down Expand Up @@ -73,7 +75,7 @@ b.bar === 1
~~~


### `caseof()`
#### `caseof()`

The `caseof()` function accepts to arguments. The first is the value to be
matched and the second is a list of constructor-function pairs. The function
Expand Down Expand Up @@ -113,6 +115,32 @@ caseof(value, [
~~~



### `import 'sum-types/caseof-eq'`

_Added in v0.9.3_

~~~js
import {caseof, otherwise} from 'sum-types/caseof-eq'
~~~

The `caseof()` function matches against patterns using strict equality (`===`).

~~~js
const result = caseof(value, [
['A', () => 'a'],
['B', 'C', () => 'bc'],
[otherwise, () => 'otherwise'],
])
~~~

If the value is `A` the result will be `a`. If the value is either `B` or `C`
the result will be `bc`. In all other cases the result will be `otherwise`.

Note that the syntax is slightly different from the main `caseof()`: Multiple
patterns are not wrapped in an array.


Motivation
----------

Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
{
"name": "sum-types",
"version": "0.9.2",
"version": "0.9.3",
"description": "Introduction and eliminiation of sum types (or tagged unions)",
"main": "index.js",
"scripts": {
"prepublish": "babel index.es6.js --out-file index.js",
"test": "eslint index.es6.js test && mocha test"
"prepublish": "babel --out-dir . src",
"test": "eslint src test && mocha test"
},
"files": [
"src",
"index.js",
"caseof-eq.js"
],
"keywords": [
"data",
"functional",
Expand Down
14 changes: 14 additions & 0 deletions src/caseof-eq.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function caseof (target, cases) {
for (const i in cases) {
const patterns = cases[i].slice()
const handler = patterns.pop()
const matches = patterns.some((p) => p === target || p === otherwise)
if (matches) {
return handler(target)
}
}

throw new Error('Unmatched case for ' + target)
}

export const otherwise = {}
File renamed without changes.
25 changes: 25 additions & 0 deletions test/caseof-eq.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {otherwise, caseof} from '../src/caseof-eq.js'
import assert from 'assert'

describe('#caseof() with equality match', function () {
it('matches correct case', function () {
const cases = [
['A', () => 'A'],
['B', () => 'B'],
['C', 'D', () => 'CD'],
[otherwise, () => null],
]

assert.equal(caseof('A', cases), 'A')
assert.equal(caseof('B', cases), 'B')
assert.equal(caseof('C', cases), 'CD')
assert.equal(caseof('D', cases), 'CD')
assert.equal(caseof('X', cases), null)
})

it('throws for unmatched target', function () {
assert.throws(() => {
caseof('A', [['B', () => null]])
}, /Unmatched case for/)
})
})
2 changes: 1 addition & 1 deletion test/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {makeSum, caseof} from '../index.es6.js'
import {makeSum, caseof} from '../src/index.js'
import assert from 'assert'

describe('#makeSum() value', function () {
Expand Down
Loading

0 comments on commit a226167

Please sign in to comment.