Advertisement
Guest User

Untitled

a guest
Jan 10th, 2017
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use strict'
  2.  
  3. let match = variant => value => cases => {
  4.     let branch = cases[variant] || cases._
  5.  
  6.     if (branch == null)
  7.         return
  8.  
  9.     if (typeof branch === 'object' && value[0].constructor === Enum)
  10.         return value[0].match(branch)
  11.  
  12.     if (typeof branch !== 'function')
  13.         throw `variant ${variant} must be a lambda`
  14.  
  15.     return branch.apply(null, value)
  16. }
  17.  
  18. let is = variant => match =>
  19.     match === variant ||
  20.     match.$name === variant
  21.  
  22. let unwrap = value => () =>
  23.     value.length > 0
  24.         ? value.length === 1
  25.             ? value[0]
  26.             : Array.from(value)
  27.         : null
  28.  
  29. let unwrapNull = () => null
  30.  
  31. function Enum(variants) {
  32.     if (arguments.length > 1)
  33.         variants = Array.from(arguments)
  34.  
  35.     let Type = function Enum(variant) {
  36.         if (typeof Enum[variant] !== 'function')
  37.             throw `undefined variant ${variant}`
  38.  
  39.         return Enum[variant]
  40.     }
  41.  
  42.     variants.forEach(variant =>
  43.         Object.assign(
  44.             Type[variant] = function() {
  45.                 return extendBase({
  46.                     match: match(variant)(arguments),
  47.                     unwrap: unwrap(arguments),
  48.                     is: is(variant)
  49.                 })
  50.             }, {
  51.                 match: match(variant)(null),
  52.                 unwrap: unwrapNull,
  53.                 is: is(variant),
  54.                 $name: variant,
  55.                 constructor: Enum
  56.             })
  57.     )
  58.  
  59.     return Type
  60. }
  61.  
  62.  
  63. let base = Object.assign(Object.create(null), {
  64.     toString: function() { return this.unwrap() },
  65.     valueOf: function() { return this.unwrap() },
  66.     constructor: Enum
  67. })
  68.  
  69. function extendBase(obj) {
  70.     return Object.assign(Object.create(base), obj)
  71. }
  72.  
  73. module.exports = Enum
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement