Skip to content

Instantly share code, notes, and snippets.

@kernalphage
Last active August 4, 2019 04:37
Show Gist options
  • Save kernalphage/2c4df7bfc27d78a0c8f20892a307f7d8 to your computer and use it in GitHub Desktop.
Save kernalphage/2c4df7bfc27d78a0c8f20892a307f7d8 to your computer and use it in GitHub Desktop.
import {_} from 'lodash';
export function makeEnum(arr){
let obj = {};
for (let val of arr){
obj[val] = Symbol(val);
}
return Object.freeze(obj);
}
// TODO: Clean this up with something smarter
// How does the saying go?
// Javascript pursues other languages down alleyways to beat them unconscious and rifle their pockets for new syntax
// This is an attempt to implement typeclasses and some metarpogramming shenenagians using
// A mixture of Symbol(), matching dictionaries, and convienent ducktyping
// Transforms: TypeData: {cat:['tail', "teeth"], bird:['wing']} => [
// {'cat':Symbol('cat'), 'bird':Symbol('bird')} // SymbolAccessor =_.mapValues(TypeData, (v,k)=>{return Symbol(k);});
// {Symbol('cat'):['tail'], Symbol('bird'):['wing']} // PropertyAccessor = _.mapKeys(TypeData, (v,k)=>{return Ex[k];});
// ]
// SymbolAccessor: string => symbol,
// PropertyAccessor: symbol => properties
export function MakeTypeclass(TypeData, ClassName){
let SymbolAccessor =_.mapValues(TypeData, (v,k)=>{return Symbol(k);});
let PropertyAccessor = _.mapKeys(TypeData, (v,k)=>{return Ex[k];});
return [TypeFactory(PropertyAccessor, ClassName), SymbolAccessor];
}
function TypeFactory(Typeclass, ClassName){
// Creates an expression of type Symbol, and populates it if possible
return function (symbol, ...args){
if(!( symbol in _.keys(Typeclass))){
throw new Exception("Symbol " + symbol + " Not in category " + ClassName);
}
let obj = _.zipObject(Typeclas[symbol], args);
obj.Type = symbol;
obj.Klass = ClassName; // Not sure if this is needed but hey, why not
return obj;
};
}
export function isSameType(a, b){
a = (a instanceof Symbol) ? a : a.Type;
b = (b instanceof Symbol) ? b : b.Type;
return a == b; // TODO: Triple equals?
}
let [MakeAnimal, AnimalTypes] = MakeTypeclass({cat:['tail'], bird:['wing']}, "Animals");
let tweety = MakeAnimal(AnimalTypes.bird, "yellow");
let sylvester = MakeAnimal(AnimalTypes.cat, "bushy", "sharp");
// And then we get pattern matching! (sort of)...
function describeAnimal(animal) {
switch(animal.Type){
case AnimalTypes.cat:
case AnimalTypes.dog:
return "mammalian";
case AnimalTypes.bird:
return "Avian";
default:
return "Unknown. Alien?";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment