From c225c058bcc2f26b0367b1eb15eaf067735c378c Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 15 Feb 2022 08:20:12 +0100 Subject: [PATCH] build --- docs/_snowpack/link/strudel.js | 17 +- docs/_snowpack/pkg/import-map.json | 1 + docs/_snowpack/pkg/ramda.js | 606 +++++++++++++++++++++++++++++ docs/dist/tonal.js | 5 +- docs/dist/tunes.js | 11 + 5 files changed, 636 insertions(+), 4 deletions(-) create mode 100644 docs/_snowpack/pkg/ramda.js diff --git a/docs/_snowpack/link/strudel.js b/docs/_snowpack/link/strudel.js index 25e8f8aa..1fec6bda 100644 --- a/docs/_snowpack/link/strudel.js +++ b/docs/_snowpack/link/strudel.js @@ -1,15 +1,20 @@ import Fraction from "../pkg/fractionjs.js"; +import {compose} from "../pkg/ramda.js"; const removeUndefineds = (xs) => xs.filter((x) => x != void 0); const flatten = (arr) => [].concat(...arr); const id = (a) => a; -export function curry(func) { +export function curry(func, overload) { return function curried(...args) { if (args.length >= func.length) { return func.apply(this, args); } else { - return function(...args2) { + const partial = function(...args2) { return curried.apply(this, args.concat(args2)); }; + if (overload) { + overload(partial, args); + } + return partial; } }; } @@ -533,6 +538,14 @@ const when = curry((binary, f, pat) => pat.when(binary, f)); const off = curry((t, f, pat) => pat.off(t, f)); const jux = curry((f, pat) => pat.jux(f)); const append = curry((a, pat) => pat.append(a)); +Pattern.prototype.composable = {fast, slow, early, late}; +export function makeComposable(func) { + Object.entries(Pattern.prototype.composable).forEach(([functionName, composable]) => { + func[functionName] = (...args) => { + return compose(func, composable(...args)); + }; + }); +} export { Fraction, TimeSpan, diff --git a/docs/_snowpack/pkg/import-map.json b/docs/_snowpack/pkg/import-map.json index e9d65f10..dc8f9809 100644 --- a/docs/_snowpack/pkg/import-map.json +++ b/docs/_snowpack/pkg/import-map.json @@ -9,6 +9,7 @@ "estraverse": "./estraverse.js", "fraction.js": "./fractionjs.js", "multimap": "./multimap.js", + "ramda": "./ramda.js", "react": "./react.js", "react-codemirror2": "./react-codemirror2.js", "react-dom": "./react-dom.js", diff --git a/docs/_snowpack/pkg/ramda.js b/docs/_snowpack/pkg/ramda.js new file mode 100644 index 00000000..4ddeeb90 --- /dev/null +++ b/docs/_snowpack/pkg/ramda.js @@ -0,0 +1,606 @@ +function _isPlaceholder(a) { + return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true; +} + +/** + * Optimized internal one-arity curry function. + * + * @private + * @category Function + * @param {Function} fn The function to curry. + * @return {Function} The curried function. + */ + +function _curry1(fn) { + return function f1(a) { + if (arguments.length === 0 || _isPlaceholder(a)) { + return f1; + } else { + return fn.apply(this, arguments); + } + }; +} + +/** + * Optimized internal two-arity curry function. + * + * @private + * @category Function + * @param {Function} fn The function to curry. + * @return {Function} The curried function. + */ + +function _curry2(fn) { + return function f2(a, b) { + switch (arguments.length) { + case 0: + return f2; + + case 1: + return _isPlaceholder(a) ? f2 : _curry1(function (_b) { + return fn(a, _b); + }); + + default: + return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function (_a) { + return fn(_a, b); + }) : _isPlaceholder(b) ? _curry1(function (_b) { + return fn(a, _b); + }) : fn(a, b); + } + }; +} + +function _arity(n, fn) { + /* eslint-disable no-unused-vars */ + switch (n) { + case 0: + return function () { + return fn.apply(this, arguments); + }; + + case 1: + return function (a0) { + return fn.apply(this, arguments); + }; + + case 2: + return function (a0, a1) { + return fn.apply(this, arguments); + }; + + case 3: + return function (a0, a1, a2) { + return fn.apply(this, arguments); + }; + + case 4: + return function (a0, a1, a2, a3) { + return fn.apply(this, arguments); + }; + + case 5: + return function (a0, a1, a2, a3, a4) { + return fn.apply(this, arguments); + }; + + case 6: + return function (a0, a1, a2, a3, a4, a5) { + return fn.apply(this, arguments); + }; + + case 7: + return function (a0, a1, a2, a3, a4, a5, a6) { + return fn.apply(this, arguments); + }; + + case 8: + return function (a0, a1, a2, a3, a4, a5, a6, a7) { + return fn.apply(this, arguments); + }; + + case 9: + return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) { + return fn.apply(this, arguments); + }; + + case 10: + return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { + return fn.apply(this, arguments); + }; + + default: + throw new Error('First argument to _arity must be a non-negative integer no greater than ten'); + } +} + +/** + * Optimized internal three-arity curry function. + * + * @private + * @category Function + * @param {Function} fn The function to curry. + * @return {Function} The curried function. + */ + +function _curry3(fn) { + return function f3(a, b, c) { + switch (arguments.length) { + case 0: + return f3; + + case 1: + return _isPlaceholder(a) ? f3 : _curry2(function (_b, _c) { + return fn(a, _b, _c); + }); + + case 2: + return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function (_a, _c) { + return fn(_a, b, _c); + }) : _isPlaceholder(b) ? _curry2(function (_b, _c) { + return fn(a, _b, _c); + }) : _curry1(function (_c) { + return fn(a, b, _c); + }); + + default: + return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function (_a, _b) { + return fn(_a, _b, c); + }) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function (_a, _c) { + return fn(_a, b, _c); + }) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function (_b, _c) { + return fn(a, _b, _c); + }) : _isPlaceholder(a) ? _curry1(function (_a) { + return fn(_a, b, c); + }) : _isPlaceholder(b) ? _curry1(function (_b) { + return fn(a, _b, c); + }) : _isPlaceholder(c) ? _curry1(function (_c) { + return fn(a, b, _c); + }) : fn(a, b, c); + } + }; +} + +/** + * Tests whether or not an object is an array. + * + * @private + * @param {*} val The object to test. + * @return {Boolean} `true` if `val` is an array, `false` otherwise. + * @example + * + * _isArray([]); //=> true + * _isArray(null); //=> false + * _isArray({}); //=> false + */ +var _isArray = Array.isArray || function _isArray(val) { + return val != null && val.length >= 0 && Object.prototype.toString.call(val) === '[object Array]'; +}; + +function _isString(x) { + return Object.prototype.toString.call(x) === '[object String]'; +} + +/** + * Tests whether or not an object is similar to an array. + * + * @private + * @category Type + * @category List + * @sig * -> Boolean + * @param {*} x The object to test. + * @return {Boolean} `true` if `x` has a numeric length property and extreme indices defined; `false` otherwise. + * @example + * + * _isArrayLike([]); //=> true + * _isArrayLike(true); //=> false + * _isArrayLike({}); //=> false + * _isArrayLike({length: 10}); //=> false + * _isArrayLike({0: 'zero', 9: 'nine', length: 10}); //=> true + * _isArrayLike({nodeType: 1, length: 1}) // => false + */ + +var _isArrayLike = +/*#__PURE__*/ +_curry1(function isArrayLike(x) { + if (_isArray(x)) { + return true; + } + + if (!x) { + return false; + } + + if (typeof x !== 'object') { + return false; + } + + if (_isString(x)) { + return false; + } + + if (x.length === 0) { + return true; + } + + if (x.length > 0) { + return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1); + } + + return false; +}); + +var XWrap = +/*#__PURE__*/ +function () { + function XWrap(fn) { + this.f = fn; + } + + XWrap.prototype['@@transducer/init'] = function () { + throw new Error('init not implemented on XWrap'); + }; + + XWrap.prototype['@@transducer/result'] = function (acc) { + return acc; + }; + + XWrap.prototype['@@transducer/step'] = function (acc, x) { + return this.f(acc, x); + }; + + return XWrap; +}(); + +function _xwrap(fn) { + return new XWrap(fn); +} + +/** + * Creates a function that is bound to a context. + * Note: `R.bind` does not provide the additional argument-binding capabilities of + * [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). + * + * @func + * @memberOf R + * @since v0.6.0 + * @category Function + * @category Object + * @sig (* -> *) -> {*} -> (* -> *) + * @param {Function} fn The function to bind to context + * @param {Object} thisObj The context to bind `fn` to + * @return {Function} A function that will execute in the context of `thisObj`. + * @see R.partial + * @example + * + * const log = R.bind(console.log, console); + * R.pipe(R.assoc('a', 2), R.tap(log), R.assoc('a', 3))({a: 1}); //=> {a: 3} + * // logs {a: 2} + * @symb R.bind(f, o)(a, b) = f.call(o, a, b) + */ + +var bind = +/*#__PURE__*/ +_curry2(function bind(fn, thisObj) { + return _arity(fn.length, function () { + return fn.apply(thisObj, arguments); + }); +}); + +function _arrayReduce(xf, acc, list) { + var idx = 0; + var len = list.length; + + while (idx < len) { + acc = xf['@@transducer/step'](acc, list[idx]); + + if (acc && acc['@@transducer/reduced']) { + acc = acc['@@transducer/value']; + break; + } + + idx += 1; + } + + return xf['@@transducer/result'](acc); +} + +function _iterableReduce(xf, acc, iter) { + var step = iter.next(); + + while (!step.done) { + acc = xf['@@transducer/step'](acc, step.value); + + if (acc && acc['@@transducer/reduced']) { + acc = acc['@@transducer/value']; + break; + } + + step = iter.next(); + } + + return xf['@@transducer/result'](acc); +} + +function _methodReduce(xf, acc, obj, methodName) { + return xf['@@transducer/result'](obj[methodName](bind(xf['@@transducer/step'], xf), acc)); +} + +var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator'; +function _reduce(fn, acc, list) { + if (typeof fn === 'function') { + fn = _xwrap(fn); + } + + if (_isArrayLike(list)) { + return _arrayReduce(fn, acc, list); + } + + if (typeof list['fantasy-land/reduce'] === 'function') { + return _methodReduce(fn, acc, list, 'fantasy-land/reduce'); + } + + if (list[symIterator] != null) { + return _iterableReduce(fn, acc, list[symIterator]()); + } + + if (typeof list.next === 'function') { + return _iterableReduce(fn, acc, list); + } + + if (typeof list.reduce === 'function') { + return _methodReduce(fn, acc, list, 'reduce'); + } + + throw new TypeError('reduce: list must be array or iterable'); +} + +/** + * Returns a single item by iterating through the list, successively calling + * the iterator function and passing it an accumulator value and the current + * value from the array, and then passing the result to the next call. + * + * The iterator function receives two values: *(acc, value)*. It may use + * [`R.reduced`](#reduced) to shortcut the iteration. + * + * The arguments' order of [`reduceRight`](#reduceRight)'s iterator function + * is *(value, acc)*. + * + * Note: `R.reduce` does not skip deleted or unassigned indices (sparse + * arrays), unlike the native `Array.prototype.reduce` method. For more details + * on this behavior, see: + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description + * + * Dispatches to the `reduce` method of the third argument, if present. When + * doing so, it is up to the user to handle the [`R.reduced`](#reduced) + * shortcuting, as this is not implemented by `reduce`. + * + * @func + * @memberOf R + * @since v0.1.0 + * @category List + * @sig ((a, b) -> a) -> a -> [b] -> a + * @param {Function} fn The iterator function. Receives two values, the accumulator and the + * current element from the array. + * @param {*} acc The accumulator value. + * @param {Array} list The list to iterate over. + * @return {*} The final, accumulated value. + * @see R.reduced, R.addIndex, R.reduceRight + * @example + * + * R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10 + * // - -10 + * // / \ / \ + * // - 4 -6 4 + * // / \ / \ + * // - 3 ==> -3 3 + * // / \ / \ + * // - 2 -1 2 + * // / \ / \ + * // 0 1 0 1 + * + * @symb R.reduce(f, a, [b, c, d]) = f(f(f(a, b), c), d) + */ + +var reduce = +/*#__PURE__*/ +_curry3(_reduce); + +function _pipe(f, g) { + return function () { + return g.call(this, f.apply(this, arguments)); + }; +} + +/** + * This checks whether a function has a [methodname] function. If it isn't an + * array it will execute that function otherwise it will default to the ramda + * implementation. + * + * @private + * @param {Function} fn ramda implementation + * @param {String} methodname property to check for a custom implementation + * @return {Object} Whatever the return value of the method is. + */ + +function _checkForMethod(methodname, fn) { + return function () { + var length = arguments.length; + + if (length === 0) { + return fn(); + } + + var obj = arguments[length - 1]; + return _isArray(obj) || typeof obj[methodname] !== 'function' ? fn.apply(this, arguments) : obj[methodname].apply(obj, Array.prototype.slice.call(arguments, 0, length - 1)); + }; +} + +/** + * Returns the elements of the given list or string (or object with a `slice` + * method) from `fromIndex` (inclusive) to `toIndex` (exclusive). + * + * Dispatches to the `slice` method of the third argument, if present. + * + * @func + * @memberOf R + * @since v0.1.4 + * @category List + * @sig Number -> Number -> [a] -> [a] + * @sig Number -> Number -> String -> String + * @param {Number} fromIndex The start index (inclusive). + * @param {Number} toIndex The end index (exclusive). + * @param {*} list + * @return {*} + * @example + * + * R.slice(1, 3, ['a', 'b', 'c', 'd']); //=> ['b', 'c'] + * R.slice(1, Infinity, ['a', 'b', 'c', 'd']); //=> ['b', 'c', 'd'] + * R.slice(0, -1, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c'] + * R.slice(-3, -1, ['a', 'b', 'c', 'd']); //=> ['b', 'c'] + * R.slice(0, 3, 'ramda'); //=> 'ram' + */ + +var slice = +/*#__PURE__*/ +_curry3( +/*#__PURE__*/ +_checkForMethod('slice', function slice(fromIndex, toIndex, list) { + return Array.prototype.slice.call(list, fromIndex, toIndex); +})); + +/** + * Returns all but the first element of the given list or string (or object + * with a `tail` method). + * + * Dispatches to the `slice` method of the first argument, if present. + * + * @func + * @memberOf R + * @since v0.1.0 + * @category List + * @sig [a] -> [a] + * @sig String -> String + * @param {*} list + * @return {*} + * @see R.head, R.init, R.last + * @example + * + * R.tail([1, 2, 3]); //=> [2, 3] + * R.tail([1, 2]); //=> [2] + * R.tail([1]); //=> [] + * R.tail([]); //=> [] + * + * R.tail('abc'); //=> 'bc' + * R.tail('ab'); //=> 'b' + * R.tail('a'); //=> '' + * R.tail(''); //=> '' + */ + +var tail = +/*#__PURE__*/ +_curry1( +/*#__PURE__*/ +_checkForMethod('tail', +/*#__PURE__*/ +slice(1, Infinity))); + +/** + * Performs left-to-right function composition. The first argument may have + * any arity; the remaining arguments must be unary. + * + * In some libraries this function is named `sequence`. + * + * **Note:** The result of pipe is not automatically curried. + * + * @func + * @memberOf R + * @since v0.1.0 + * @category Function + * @sig (((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)) -> ((a, b, ..., n) -> z) + * @param {...Function} functions + * @return {Function} + * @see R.compose + * @example + * + * const f = R.pipe(Math.pow, R.negate, R.inc); + * + * f(3, 4); // -(3^4) + 1 + * @symb R.pipe(f, g, h)(a, b) = h(g(f(a, b))) + * @symb R.pipe(f, g, h)(a)(b) = h(g(f(a)))(b) + */ + +function pipe() { + if (arguments.length === 0) { + throw new Error('pipe requires at least one argument'); + } + + return _arity(arguments[0].length, reduce(_pipe, arguments[0], tail(arguments))); +} + +/** + * Returns a new list or string with the elements or characters in reverse + * order. + * + * @func + * @memberOf R + * @since v0.1.0 + * @category List + * @sig [a] -> [a] + * @sig String -> String + * @param {Array|String} list + * @return {Array|String} + * @example + * + * R.reverse([1, 2, 3]); //=> [3, 2, 1] + * R.reverse([1, 2]); //=> [2, 1] + * R.reverse([1]); //=> [1] + * R.reverse([]); //=> [] + * + * R.reverse('abc'); //=> 'cba' + * R.reverse('ab'); //=> 'ba' + * R.reverse('a'); //=> 'a' + * R.reverse(''); //=> '' + */ + +var reverse = +/*#__PURE__*/ +_curry1(function reverse(list) { + return _isString(list) ? list.split('').reverse().join('') : Array.prototype.slice.call(list, 0).reverse(); +}); + +/** + * Performs right-to-left function composition. The last argument may have + * any arity; the remaining arguments must be unary. + * + * **Note:** The result of compose is not automatically curried. + * + * @func + * @memberOf R + * @since v0.1.0 + * @category Function + * @sig ((y -> z), (x -> y), ..., (o -> p), ((a, b, ..., n) -> o)) -> ((a, b, ..., n) -> z) + * @param {...Function} ...functions The functions to compose + * @return {Function} + * @see R.pipe + * @example + * + * const classyGreeting = (firstName, lastName) => "The name's " + lastName + ", " + firstName + " " + lastName + * const yellGreeting = R.compose(R.toUpper, classyGreeting); + * yellGreeting('James', 'Bond'); //=> "THE NAME'S BOND, JAMES BOND" + * + * R.compose(Math.abs, R.add(1), R.multiply(2))(-4) //=> 7 + * + * @symb R.compose(f, g, h)(a, b) = f(g(h(a, b))) + * @symb R.compose(f, g, h)(a)(b) = f(g(h(a)))(b) + */ + +function compose() { + if (arguments.length === 0) { + throw new Error('compose requires at least one argument'); + } + + return pipe.apply(this, reverse(arguments)); +} + +export { compose }; diff --git a/docs/dist/tonal.js b/docs/dist/tonal.js index 4f5a0950..0442f44a 100644 --- a/docs/dist/tonal.js +++ b/docs/dist/tonal.js @@ -1,5 +1,5 @@ import {Note, Interval, Scale} from "../_snowpack/pkg/@tonaljs/tonal.js"; -import {Pattern as _Pattern, curry} from "../_snowpack/link/strudel.js"; +import {Pattern as _Pattern, curry, makeComposable} from "../_snowpack/link/strudel.js"; const Pattern = _Pattern; function toNoteEvent(event) { if (typeof event === "string") { @@ -55,7 +55,7 @@ Pattern.prototype._transpose = function(intervalOrSemitones) { return {value: Note.transpose(value, interval), scale}; }); }; -export const transpose = curry((a, pat) => pat.transpose(a)); +export const transpose = curry((a, pat) => pat.transpose(a), (partial) => makeComposable(partial)); Pattern.prototype._scaleTranspose = function(offset) { return this._mapNotes(({value, scale}) => { if (!scale) { @@ -68,3 +68,4 @@ Pattern.prototype._scale = function(scale) { return this._mapNotes((value) => ({...value, scale})); }; Pattern.prototype.patternified = Pattern.prototype.patternified.concat(["transpose", "scaleTranspose", "scale"]); +Object.assign(Pattern.prototype.composable, {transpose}); diff --git a/docs/dist/tunes.js b/docs/dist/tunes.js index e4b8a408..798c5093 100644 --- a/docs/dist/tunes.js +++ b/docs/dist/tunes.js @@ -330,4 +330,15 @@ export const confusedPhoneDynamic = `stack('[g2 ~@1.3] [c3 ~@1.3]'.mini.slow(2)) .scale(sequence('C dorian', 'C mixolydian').slow(4)) .scaleTranspose(slowcat(0,1,2,1).slow(2)) .synth('triangle').gain(0.2).filter(1500)`; +export const confusedPhonePartial = `stack('[g2 ~@1.3] [c3 ~@1.3]'.mini.slow(2)) +.superimpose( + transpose(-12).late(0), + transpose(7).late(0.2), + transpose(10).late(0.4), + transpose(12).late(0.6), + transpose(24).late(0.8) +) +.scale(sequence('C dorian', 'C mixolydian').slow(4)) +.scaleTranspose(slowcat(0,1,2,1).slow(2)) +.synth('triangle').gain(0.2).filter(1500)`; export default swimming;