Skip to content

Instantly share code, notes, and snippets.

@trxcllnt
Last active July 30, 2016 01:42
Show Gist options
  • Save trxcllnt/0da8f24ad5c54c2e64c217d90b131c5f to your computer and use it in GitHub Desktop.
Save trxcllnt/0da8f24ad5c54c2e64c217d90b131c5f to your computer and use it in GitHub Desktop.
esnextbin sketch
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ESNextbin Sketch</title>
<!-- put additional styles and scripts here -->
</head>
<body>
<!-- put markup and other contents here -->
<div id="app"></div>
</body>
</html>
/*
* Specify required named properties for classes that take an object as
* their first argument. Curry the class constructor until all required
* properties are provided. When all properties are required, return an
* instance of the curried class. Maintains prototype constructors so
* curried classes can be extended.
*/
const MyClass = curryClass(['required', 'props'], class MyClass {
constructor(props, ...rest) {
console.log(this.constructor.name, JSON.stringify(props), ...rest);
this.someMethod();
}
someMethod() {
console.log(`${this.constructor.name}, 'someMethod' base impl`);
}
});
const MyClassPartialWithNew = new MyClass({ props: 'props value' });
const MyClassPartial = /**/MyClass({ props: 'props value' });
/* curried ctors ^ can also be called without `new` */
class MyPartialSublass extends MyClassPartial {
someMethod() {
console.log(`${this.constructor.name}, 'someMethod' subclass partial impl`);
}
}
class MySubclass extends MyClass {
someMethod() {
console.log(`${this.constructor.name}, 'someMethod' subclass impl`);
}
}
console.clear();
const PartialInstance1 = MyClassPartial({ required: 'property A' });
const PartialInstance2 = new MyClassPartialWithNew({ required: 'property B' });
const PartialSublassInstance = new MyPartialSublass({ required: 'property C'});
const SubclassPartial1 = new MySubclass({ props: 'other value' }, [1, 2, 3]);
const SubclassPartial2 = SubclassPartial1({ additional: 'property' }, [4, 5, 6]);
const SubclassPartial3 = new SubclassPartial1({ additional: 'property' }, [4, 5, 6]);
const SubclassInstance1 = new SubclassPartial2({ required: 'foo' }, [7, 8, 9]);
const SubclassInstance2 = new SubclassPartial3({ required: 'bar', more: 'props' }, [10, 11, 12]);
console.log(PartialInstance1 instanceof MyClass);
console.log(PartialInstance2 instanceof MyClass);
console.log(PartialSublassInstance instanceof MyClass);
console.log(SubclassInstance1 instanceof MyClass);
console.log(SubclassInstance2 instanceof MyClass);
console.log(SubclassInstance1 instanceof MySubclass);
console.log(SubclassInstance2 instanceof MySubclass);
function curryClass(args, ctor, opts = {}, rest = []) {
curriedCtor.prototype = Object.create(ctor.prototype);
return curriedCtor;
function curriedCtor(attr, ...more) {
const argsLeft = attr && args.filter((prop) => !attr.hasOwnProperty(prop));
const restArgs = rest.concat(more);
const restOpts = {...opts, ...attr};
// If required args remain, curry to the ctor again
if (argsLeft && argsLeft.length) {
// If `this` is a subclass of the curried ctor, curry to `this.constructor`.
// If `this` is an instance of the curried ctor, or if `this` isn't an isntance
// of the curried ctor, curry to the captured `curriedCtor` ctor.
const nextCtor = this && this instanceof ctor && this.constructor || ctor;
if (nextCtor !== ctor) {
return curryClass(argsLeft, nextCtor, restOpts, restArgs);
}
function nextCurriedCtor() {
return ctor.apply(this, arguments);
}
nextCurriedCtor.prototype = Object.create(curriedCtor.prototype);
return curryClass(argsLeft, nextCurriedCtor, restOpts, restArgs);
}
////
// Otherwise, no args left to curry. Invoke or
// instantiate the curried ctor with the aggregated
// props and args.
////
// If `this` is an instance of the curried ctor, the
// curried result was called using `new`. Return the
// call to the curried ctor.
else if (this instanceof ctor) {
return ctor.call(this, restOpts, ...restArgs);
}
////
// If `this` isn't an instance of the curried ctor,
// the curried result was called without using `new`.
// Instantiate and return an instance of the curried ctor.
////
else {
return new ctor(restOpts, ...restArgs);
}
}
}
{
"name": "esnextbin-sketch",
"version": "0.0.0",
"dependencies": {
"babel-runtime": "6.11.6"
}
}
'use strict';
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _create = require('babel-runtime/core-js/object/create');
var _create2 = _interopRequireDefault(_create);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
* Specify required named properties for classes that take an object as
* their first argument. Curry the class constructor until all required
* properties are provided. When all properties are required, return an
* instance of the curried class. Maintains prototype constructors so
* curried classes can be extended.
*/
var MyClass = curryClass(['required', 'props'], function () {
function MyClass(props) {
var _console;
(0, _classCallCheck3.default)(this, MyClass);
for (var _len = arguments.length, rest = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
rest[_key - 1] = arguments[_key];
}
(_console = console).log.apply(_console, [this.constructor.name, (0, _stringify2.default)(props)].concat(rest));
this.someMethod();
}
(0, _createClass3.default)(MyClass, [{
key: 'someMethod',
value: function someMethod() {
console.log(this.constructor.name + ', \'someMethod\' base impl');
}
}]);
return MyClass;
}());
var MyClassPartialWithNew = new MyClass({ props: 'props value' });
var MyClassPartial = /**/MyClass({ props: 'props value' });
/* curried ctors ^ can also be called without `new` */
var MyPartialSublass = function (_MyClassPartial) {
(0, _inherits3.default)(MyPartialSublass, _MyClassPartial);
function MyPartialSublass() {
(0, _classCallCheck3.default)(this, MyPartialSublass);
return (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(MyPartialSublass).apply(this, arguments));
}
(0, _createClass3.default)(MyPartialSublass, [{
key: 'someMethod',
value: function someMethod() {
console.log(this.constructor.name + ', \'someMethod\' subclass partial impl');
}
}]);
return MyPartialSublass;
}(MyClassPartial);
var MySubclass = function (_MyClass) {
(0, _inherits3.default)(MySubclass, _MyClass);
function MySubclass() {
(0, _classCallCheck3.default)(this, MySubclass);
return (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(MySubclass).apply(this, arguments));
}
(0, _createClass3.default)(MySubclass, [{
key: 'someMethod',
value: function someMethod() {
console.log(this.constructor.name + ', \'someMethod\' subclass impl');
}
}]);
return MySubclass;
}(MyClass);
console.clear();
var PartialInstance1 = MyClassPartial({ required: 'property A' });
var PartialInstance2 = new MyClassPartialWithNew({ required: 'property B' });
var PartialSublassInstance = new MyPartialSublass({ required: 'property C' });
var SubclassPartial1 = new MySubclass({ props: 'other value' }, [1, 2, 3]);
var SubclassPartial2 = SubclassPartial1({ additional: 'property' }, [4, 5, 6]);
var SubclassPartial3 = new SubclassPartial1({ additional: 'property' }, [4, 5, 6]);
var SubclassInstance1 = new SubclassPartial2({ required: 'foo' }, [7, 8, 9]);
var SubclassInstance2 = new SubclassPartial3({ required: 'bar', more: 'props' }, [10, 11, 12]);
console.log(PartialInstance1 instanceof MyClass);
console.log(PartialInstance2 instanceof MyClass);
console.log(PartialSublassInstance instanceof MyClass);
console.log(SubclassInstance1 instanceof MyClass);
console.log(SubclassInstance2 instanceof MyClass);
console.log(SubclassInstance1 instanceof MySubclass);
console.log(SubclassInstance2 instanceof MySubclass);
function curryClass(args, ctor) {
var opts = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var rest = arguments.length <= 3 || arguments[3] === undefined ? [] : arguments[3];
curriedCtor.prototype = (0, _create2.default)(ctor.prototype);
return curriedCtor;
function curriedCtor(attr) {
for (var _len2 = arguments.length, more = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
more[_key2 - 1] = arguments[_key2];
}
var argsLeft = attr && args.filter(function (prop) {
return !attr.hasOwnProperty(prop);
});
var restArgs = rest.concat(more);
var restOpts = (0, _extends3.default)({}, opts, attr);
// If required args remain, curry to the ctor again
if (argsLeft && argsLeft.length) {
var nextCurriedCtor = function nextCurriedCtor() {
return ctor.apply(this, arguments);
};
// If `this` is a subclass of the curried ctor, curry to `this.constructor`.
// If `this` is an instance of the curried ctor, or if `this` isn't an isntance
// of the curried ctor, curry to the captured `curriedCtor` ctor.
var nextCtor = this && this instanceof ctor && this.constructor || ctor;
if (nextCtor !== ctor) {
return curryClass(argsLeft, nextCtor, restOpts, restArgs);
}
nextCurriedCtor.prototype = (0, _create2.default)(curriedCtor.prototype);
return curryClass(argsLeft, nextCurriedCtor, restOpts, restArgs);
}
////
// Otherwise, no args left to curry. Invoke or
// instantiate the curried ctor with the aggregated
// props and args.
////
// If `this` is an instance of the curried ctor, the
// curried result was called using `new`. Return the
// call to the curried ctor.
else if (this instanceof ctor) {
return ctor.call.apply(ctor, [this, restOpts].concat((0, _toConsumableArray3.default)(restArgs)));
}
////
// If `this` isn't an instance of the curried ctor,
// the curried result was called without using `new`.
// Instantiate and return an instance of the curried ctor.
////
else {
return new (Function.prototype.bind.apply(ctor, [null].concat([restOpts], (0, _toConsumableArray3.default)(restArgs))))();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment