diff --git a/packages/core/evaluate.mjs b/packages/core/evaluate.mjs index 35c47e42..fc1d1078 100644 --- a/packages/core/evaluate.mjs +++ b/packages/core/evaluate.mjs @@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { isPattern, Pattern } from './index.mjs'; +import { isPattern } from './index.mjs'; let scoped = false; export const evalScope = async (...args) => { @@ -19,7 +19,7 @@ export const evalScope = async (...args) => { console.warn(`evalScope: module with index ${i} could not be loaded:`, result.reason); } }); - Object.assign(globalThis, ...modules, Pattern.prototype.bootstrap()); + Object.assign(globalThis, ...modules); }; function safeEval(str, options = {}) { diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 2985741a..803ad0eb 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -581,21 +581,6 @@ export class Pattern { ); } - patternify(join, func) { - const pat = this; - return function (...args) { - // the problem here: args could be a pattern that has been - // turned into an object to add location to avoid object - // checking for every pattern method, we can remove it here... - // in the future, patternified args should be marked as well + - // some better object handling - args = args.map((arg) => (isPattern(arg) ? arg.fmap((value) => value.value || value) : arg)); - const pat_arg = sequence(...args); - // arg.locations has to go somewhere.. - return join(pat_arg.fmap((arg) => func.call(pat, arg))); - }; - } - asNumber() { return this.fmap(parseNumeral); } @@ -1921,83 +1906,3 @@ const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat) const { loopAtCps, loopatcps } = register(['loopAtCps', 'loopatcps'], function (factor, cps, pat) { return _loopAt(factor, pat, cps); }); - -// problem: curried functions with spread arguments must have pat at the beginning -// with this, we cannot keep the pattern open at the end.. solution for now: use array to keep using pat as last arg - -// these are the core composable functions. they are extended with Pattern.prototype.define below -Pattern.prototype.composable = { early, late, superimpose }; - -// adds Pattern.prototype.composable to given function as child functions -// then you can do transpose(2).late(0.2) instead of x => x.transpose(2).late(0.2) -export function makeComposable(func) { - Object.entries(Pattern.prototype.composable).forEach(([functionName, composable]) => { - // compose with dot - func[functionName] = (...args) => { - // console.log(`called ${functionName}(${args.join(',')})`); - const composition = compose(func, composable(...args)); - // the composition itself must be composable too :) - // then you can do endless chaining transpose(2).late(0.2).fast(2) ... - return makeComposable(composition); - }; - }); - return func; -} - -export const patternify = (f) => (pata, pat) => pata.fmap((a) => f.call(pat, a)).innerJoin(); -export const patternify2 = (f) => - function (pata, patb, pat) { - return pata - .fmap((a) => (b) => f.call(pat, a, b)) - .appLeft(patb) - .innerJoin(); - }; -export const patternify3 = (f) => (pata, patb, patc, pat) => - pata - .fmap((a) => (b) => (c) => f.call(pat, a, b, c)) - .appLeft(patb) - .appLeft(patc) - .innerJoin(); -export const patternify4 = (f) => (pata, patb, patc, patd, pat) => - pata - .fmap((a) => (b) => (c) => (d) => f.call(pat, a, b, c, d)) - .appLeft(patb) - .appLeft(patc) - .appLeft(patd) - .innerJoin(); - -Pattern.prototype.patternified = []; - -// call this after all Pattern.prototype.define calls have been executed! (right before evaluate) -Pattern.prototype.bootstrap = function () { - const bootstrapped = Object.fromEntries( - Object.entries(Pattern.prototype.composable).map(([functionName, composable]) => { - if (Pattern.prototype[functionName]) { - // without this, 'C^7'.m.chordBass.transpose(2) will throw "C^7".m.chordBass.transpose is not a function - // Pattern.prototype[functionName] = makeComposable(Pattern.prototype[functionName]); // is this needed? - } - return [functionName, curry(composable, makeComposable)]; - }), - ); - - this.patternified.forEach((prop) => { - // the following will patternify all functions in Pattern.prototype.patternified - Pattern.prototype[prop] = function (...args) { - return this.patternify((x) => x.innerJoin(), Pattern.prototype['_' + prop])(...args); - }; - }); - return bootstrapped; -}; - -// this will add func as name to list of composable / patternified functions. -// those lists will be used in bootstrap to curry and compose everything, to support various call patterns -Pattern.prototype.define = (name, func, options = {}) => { - if (options.composable) { - Pattern.prototype.composable[name] = func; - } - if (options.patternified) { - Pattern.prototype.patternified = Pattern.prototype.patternified.concat([name]); - } - - Pattern.prototype.bootstrap(); // automatically bootstrap after new definition -}; diff --git a/packages/eval/shapeshifter.mjs b/packages/eval/shapeshifter.mjs index b8ffffd3..f2edf604 100644 --- a/packages/eval/shapeshifter.mjs +++ b/packages/eval/shapeshifter.mjs @@ -225,9 +225,8 @@ function isPatternArg(parents) { function hasModifierCall(parent) { // TODO: modifiers are more than composables, for example every is not composable but should be seen as modifier.. // need all prototypes of Pattern - return ( - parent?.type === 'StaticMemberExpression' && Object.keys(Pattern.prototype.composable).includes(parent.property) - ); + return parent?.type === 'StaticMemberExpression'; + // && Object.keys(Pattern.prototype.composable).includes(parent.property) } const factories = Object.keys(Pattern.prototype.factories).concat(['mini']); diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index f2188a74..dd2445dc 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -90,8 +90,6 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa }); // example: transpose(3).late(0.2) will be equivalent to compose(transpose(3), late(0.2)) -// TODO: add Pattern.define(name, function, options) that handles all the meta programming stuff -// TODO: find out how to patternify this function when it's standalone // e.g. `stack(c3).superimpose(transpose(slowcat(7, 5)))` or // or even `stack(c3).superimpose(transpose.slowcat(7, 5))` or diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index 52650d65..532957fa 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -4,7 +4,6 @@ Copyright (C) 2022 Strudel contributors - see . */ -// import { Pattern, getFrequency, patternify2 } from '@strudel.cycles/core'; import * as strudel from '@strudel.cycles/core'; import { fromMidi, logger, toMidi } from '@strudel.cycles/core'; import './feedbackdelay.mjs'; diff --git a/repl/src/runtime.mjs b/repl/src/runtime.mjs index 294cde11..b261654a 100644 --- a/repl/src/runtime.mjs +++ b/repl/src/runtime.mjs @@ -158,7 +158,6 @@ const loadSoundfont = () => {}; evalScope( // Tone, strudel, - strudel.Pattern.prototype.bootstrap(), toneHelpersMocked, uiHelpersMocked, controls, diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index b468d948..582b1a33 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -757,8 +757,6 @@ Turns chord symbols into voicings, using the smoothest voice leading possible: ".voicings('lefthand'), "").note()`} /> - - ### rootNotes(octave = 2) Turns chord symbols into root notes of chords in given octave.