Skip to content

Instantly share code, notes, and snippets.

@lagagain
Last active February 18, 2021 13:50
Show Gist options
  • Save lagagain/3419295fd10d0d1e140437b57d942f27 to your computer and use it in GitHub Desktop.
Save lagagain/3419295fd10d0d1e140437b57d942f27 to your computer and use it in GitHub Desktop.
[javascript] Maybe / Box
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
}
}
{
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