Add pattern composers, implements #82

This commit is contained in:
alex 2022-04-21 14:13:26 +01:00
parent 36d1a68b9a
commit b370c405da
2 changed files with 60 additions and 25 deletions

View File

@ -275,14 +275,14 @@ const generic_params = [
const _name = (name, ...pats) => sequence(...pats).withValue((x) => ({ [name]: x }));
const _unionise = (func) =>
const _setter = (func) =>
function (...pats) {
return this.union(func(...pats));
return this.set(func(...pats));
};
generic_params.forEach(([type, name, description]) => {
controls[name] = (...pats) => _name(name, ...pats);
Pattern.prototype[name] = _unionise(controls[name]);
Pattern.prototype[name] = _setter(controls[name]);
});
export default controls;

View File

@ -247,9 +247,24 @@ export class Pattern {
);
}
_opleft(other, func) {
_opLeft(other, func) {
return this.fmap(func).appLeft(reify(other));
}
_opRight(other, func) {
return this.fmap(func).appRight(reify(other));
}
_opBoth(other, func) {
return this.fmap(func).appBoth(reify(other));
}
_opSqueeze(other, func) {
const otherPat = reify(other);
return this.fmap((a) => otherPat.fmap((b) => func(a)(b)))._squeezeJoin();
}
_opSqueezeFlip(other, func) {
const thisPat = this;
const otherPat = reify(other);
return otherPat.fmap((a) => thisPat.fmap((b) => func(a)(b)))._squeezeJoin();
}
_asNumber(silent = false) {
return this._withEvent((event) => {
@ -275,22 +290,6 @@ export class Pattern {
})._removeUndefineds();
}
add(other) {
return this._asNumber()._opleft(other, (a) => (b) => a + b);
}
sub(other) {
return this._asNumber()._opleft(other, (a) => (b) => a - b);
}
mul(other) {
return this._asNumber()._opleft(other, (a) => (b) => a * b);
}
div(other) {
return this._asNumber()._opleft(other, (a) => (b) => a / b);
}
round() {
return this._asNumber().fmap((v) => Math.round(v));
}
@ -324,10 +323,6 @@ export class Pattern {
return this._fromBipolar().range(min, max);
}
union(other) {
return this._opleft(other, (a) => (b) => Object.assign({}, a, b));
}
_bindWhole(choose_whole, func) {
const pat_val = this;
const query = function (state) {
@ -719,6 +714,46 @@ export class Pattern {
_velocity(velocity) {
return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
}
add(other) {
return this._asNumber()._opLeft(other, (a) => (b) => a + b);
}
sub(other) {
return this._asNumber()._opLeft(other, (a) => (b) => a - b);
}
mul(other) {
return this._asNumber()._opLeft(other, (a) => (b) => a * b);
}
div(other) {
return this._asNumber()._opLeft(other, (a) => (b) => a / b);
}
}
// pattern composers
const composers = {
set: [(a) => (b) => Object.assign({}, a, b), id],
add: [(a) => (b) => a + b, (x) => x._asNumber()],
sub: [(a) => (b) => a - b, (x) => x._asNumber()],
mul: [(a) => (b) => a * b, (x) => x._asNumber()],
div: [(a) => (b) => a / b, (x) => x._asNumber()],
};
for (const [name, op] of Object.entries(composers)) {
console.log(`Adding ${name}`);
Pattern.prototype[name] = function (other) {
return op[1](this)._opLeft(other, op[0]);
};
Pattern.prototype[name + 'Flip'] = function (other) {
return op[1](this)._opRight(other, op[0]);
};
Pattern.prototype[name + 'Sect'] = function (other) {
return op[1](this)._opBoth(other, op[0]);
};
Pattern.prototype[name + 'Squeeze'] = function (other) {
return op[1](this)._opSqueeze(other, op[0]);
};
}
// methods of Pattern that get callable factories
@ -922,7 +957,7 @@ export const slow = curry((a, pat) => pat.slow(a));
export const struct = curry((a, pat) => pat.struct(a));
export const sub = curry((a, pat) => pat.sub(a));
export const superimpose = curry((array, pat) => pat.superimpose(...array));
export const union = curry((a, pat) => pat.union(a));
export const set = curry((a, pat) => pat.set(a));
export const when = curry((binary, f, pat) => pat.when(binary, f));
// problem: curried functions with spread arguments must have pat at the beginning