Making a shorthand for a synth or any combination of chained functions?

Hello there,

I've got these two expressions in my strudel editbox:

note("<[[f2 g2 f2 ~] c2*8]!3 [f2 c2 a1 e2]>").s("saw, sine").lpf(100)

and a little further down:

note("f2@3 ~").s("saw, sine").lpf(200),

is it possible to somehow factor out the .s("saw, sine").lpf(200) part into another function, called something like mybass or similar? Essentially I'd like to be able to do something like this:

note("...").mybass( // ...more effects if I want to

Thanks in advance for your help!

Ha! Javascript puzzle time.

Just looking at the expressions, and without any knowledge of internals, I expect that you could add the method mybass to (what I expect to be) the prototype/class of strudel objects

// I guess strudel has something like
base =  { foo(x) {  this.f = x; return this } , bar(x) { this.b = x; return this } }
// that can be used like
ob =  { __proto__ : base }
ob.foo(1).bar(2) // result: { f: 1, b: 2 }

// your function
base.my = function ()  {return this.foo(3).bar(4)}
// use it
ob.my() // result: { f: 3, b: 4 }
// and you can combine it
ob.my().bar(0) // result { f: 3, b: 0 }

in reality, types will be different (not numeric), but since JS has no (static) types, it should still work. Does it?

1 Like

Hello, thanks for your answer.

I was considering something similar, but I wanted to ask here first in case there was a less hacky way to do it.
This is what I did to do what I said in the OP:

const patproto = silence.__proto__;
patproto.mybass = function() { return this.s("saw, sine").lpf(200); };

// I use it like this
note("c d e f").mybass()

This option works and isn't that hard, but if you aren't careful with the name you give your custom functions you can get in trouble. For example if a future version of strudel gets a mybass function my code would clobber it which could have unexpected consequences.

Would the developers of strudel be interested in having a standard way for users to make their own chain functions? Perhaps something like this:

adduserfunc("mybass", function() { return this.s("saw, sine").lpf(200); });

note("c a f e").user("mybass");
1 Like

yes.

in that hypothetical future strudel,

the base object could seal/freeze its attributes? (the your mybass would just be ignored.)

if you want two different meanings of mybass, you could put them at different objects in the __proto__ chain, but using them seems hard.

perhaps someting with prototype in addition to/in place of __proto__ works?

this is definitely "worse than Haskell" territory (for me). might still be useful as an exercise...

there is already a way to do this:

let mybass = register('mybass', x=>x.s("saw,sine").lpf(200))
2 Likes

but be careful: it’s worse than haskell :wink:

1 Like

Thank you for the response, that turned out to be exactly what I wanted.

1 Like

now I want to know how you do it ... indeed .prototype is used somehow, https://codeberg.org/uzu/strudel/src/branch/main/packages/core/pattern.mjs#L1649 That's a whole new world of coding horrors. I will return to Haskell land now, enough horror there.