Last active
February 18, 2021 13:50
-
-
Save lagagain/3419295fd10d0d1e140437b57d942f27 to your computer and use it in GitHub Desktop.
[javascript] Maybe / Box
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function wrap(value){ | |
switch(typeof value){ | |
case 'number': | |
return new Number(value) | |
case 'string': | |
return new String(value) | |
case 'boolean': | |
return new Boolean(value) | |
case 'symbol': | |
case 'undefined': | |
case 'bigint': { | |
let ret = {valueOf: ()=>value} | |
ret.__proto__ = wrap.prototype; | |
return ret; | |
} | |
case 'function': | |
case 'object': | |
if (value === null){ | |
let ret = {valueOf: ()=>value} | |
ret.__proto__ = wrap.prototype; | |
return ret; | |
} else{ | |
return value | |
} | |
} | |
} | |
class Maybe { | |
static map = new WeakMap() | |
static unwrap(maybe){ | |
let value = Maybe.map.get(maybe) | |
if(value instanceof String || | |
value instanceof Number || | |
value instanceof Boolean || | |
value instanceof wrap | |
){ | |
return value.valueOf() | |
} else { | |
return value | |
} | |
} | |
static handler = { | |
get(target, prop, recevier){ | |
try { | |
if(Reflect.has(target, prop)){ | |
return new Maybe(target[prop]) | |
} | |
return new Maybe(undefined) | |
} catch(e){ | |
return new Maybe(e) | |
} | |
}, | |
set(target, prop, value, receiver){ | |
try { | |
if(prop === "valueOf"){ | |
return new Maybe(new Error("Can not setting valueOf")); | |
} else { | |
return new Maybe(target[prop] = value) | |
} | |
} catch(e) { | |
return new Maybe(e) | |
} | |
}, | |
apply(target, thisArg, argumentsList){ | |
try { | |
return new Maybe(target.apply(thisArg, argumentsList)); | |
} catch(e){ | |
return new Maybe(e) | |
} | |
}, | |
} | |
constructor(target){ | |
try{ | |
target = wrap(target) | |
let pry = new Proxy(target, Maybe.handler); | |
Maybe.map.set(pry, target); | |
return pry | |
} catch (e) { | |
target = wrap(e) | |
let pry = new Proxy(target, Maybe.handler); | |
Maybe.map.set(pry, target); | |
return pry | |
} | |
} | |
} | |
class MaybeUnwrapable extends Maybe { | |
constructor(target){ | |
let maybe = super(target) | |
let pry = new Proxy(maybe, { | |
get(maybe, prop){ | |
if(prop === "unwrap"){ | |
return Maybe.unwrap.bind(null, maybe) | |
} else if(prop === "then"){ | |
let f = (callback) => { | |
return new MaybeUnwrapable(callback(Maybe.unwrap(maybe))) | |
} | |
return f | |
} else { | |
return new MaybeUnwrapable(Maybe.unwrap(maybe[prop])) | |
} | |
} | |
}) | |
Maybe.map.set(pry, target); | |
return pry | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
console.group("Number") | |
let one = new MaybeUnwrapable(1); | |
console.assert(one instanceof Number, `[Fail] one instance of Number`) | |
console.assert(one.unwrap() + 10 === 11, `[Fail] one.unwrap() + 10 === 11`) | |
console.assert(one.then(v => v + 10).unwrap() === 11,'[Fail] one.then(v => v + 10).unwrap() === 11') | |
console.assert(one.then(v=>v+"abc").unwrap() === "1abc", `[Fail] one.then(v=>v+"abc").unwrap() === "1abc"`) | |
console.info("[Finish] test Nubmer") | |
console.groupEnd() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment