Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict'
- let match = variant => value => cases => {
- let branch = cases[variant] || cases._
- if (branch == null)
- return
- if (typeof branch === 'object' && value[0].constructor === Enum)
- return value[0].match(branch)
- if (typeof branch !== 'function')
- throw `variant ${variant} must be a lambda`
- return branch.apply(null, value)
- }
- let is = variant => match =>
- match === variant ||
- match.$name === variant
- let unwrap = value => () =>
- value.length > 0
- ? value.length === 1
- ? value[0]
- : Array.from(value)
- : null
- let unwrapNull = () => null
- function Enum(variants) {
- if (arguments.length > 1)
- variants = Array.from(arguments)
- let Type = function Enum(variant) {
- if (typeof Enum[variant] !== 'function')
- throw `undefined variant ${variant}`
- return Enum[variant]
- }
- variants.forEach(variant =>
- Object.assign(
- Type[variant] = function() {
- return extendBase({
- match: match(variant)(arguments),
- unwrap: unwrap(arguments),
- is: is(variant)
- })
- }, {
- match: match(variant)(null),
- unwrap: unwrapNull,
- is: is(variant),
- $name: variant,
- constructor: Enum
- })
- )
- return Type
- }
- let base = Object.assign(Object.create(null), {
- toString: function() { return this.unwrap() },
- valueOf: function() { return this.unwrap() },
- constructor: Enum
- })
- function extendBase(obj) {
- return Object.assign(Object.create(base), obj)
- }
- module.exports = Enum
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement