Skip to content

Instantly share code, notes, and snippets.

@raganwald
Last active August 29, 2015 14:03
Show Gist options
  • Save raganwald/8eecdac2e7ecd4743305 to your computer and use it in GitHub Desktop.
Save raganwald/8eecdac2e7ecd4743305 to your computer and use it in GitHub Desktop.
Records, Values, and Structs
function Record (template) {
if (Record.prototype.isPrototypeOf(this)) {
var struct = this;
Object.keys(template).forEach(function (key) {
Object.defineProperty(struct, key, {
enumerable: true,
writable: true,
value: template[key]
});
});
return Object.preventExtensions(struct);
}
else return new Record(template);
}
function Struct () {
var name = arguments[0],
keys = [].slice.call(arguments, 1),
constructor = eval("(function "+name+"(argument) { return initialize.call(this, argument); })");
function initialize (argument) {
if (constructor.prototype.isPrototypeOf(this)) {
var argument = argument,
struct = this;
keys.forEach(function (key) {
Object.defineProperty(struct, key, {
enumerable: true,
writable: true,
value: argument[key]
});
});
return Object.preventExtensions(struct);
}
else return constructor.prototype.isPrototypeOf(argument);
};
constructor.assertIsPrototypeOf = function (argument) {
if (!constructor.prototype.isPrototypeOf(argument)) {
var name = constructor.name === ''
? "Struct(" + keys.join(", ") + ")"
: constructor.name;
throw "Type Error: " + argument + " is not a " + name;
}
else return argument;
}
return constructor;
}
var Value = (function () {
function Value (template) {
if (Value.prototype.isPrototypeOf(this)) {
var immutableObject = this;
Object.keys(template).forEach(function (key) {
Object.defineProperty(immutableObject, key, {
enumerable: true,
writable: false,
value: template[key]
});
});
return Object.preventExtensions(immutableObject);
}
else return new Value(template);
}
Value.prototype = new Record({});
function eqv (a, b) {
var akeys, bkeys;
if (a === b) {
return true;
}
else if (a instanceof Value && b instanceof Value){
akeys = Object.keys(a);
bkeys = Object.keys(b);
if (akeys.length !== bkeys.length) {
return false;
}
else return akeys.every(function (key) {
return eqv(a[key], b[key]);
});
}
else return false;
}
Value.eqv = eqv;
Value.prototype.eqv = function (that) {
return eqv(this, that);
};
return Value;
})();
@raganwald
Copy link
Author

Extracted from JavaScript Spessore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment