patcherargs loading order

hepi's icon

I realt think patcherargs should fire BEFORE it's parent patcher's loadbang, not AFTER.

Who is with me ?

I see patcherargs as the constructor of an abstract patcher. As a typical constructor, it runs before any interaction with the object is allowed. By firing AFTER the parent patcher's loadbang, it allows interaction before the abstract patcher finished initialization.

Am I missing something?

See also end of

And

TFL's icon

9 years later... YES I'm with you! Or am I missing something too?
I just discovered this behavior and it drives me nuts. To me it seems that [patcher] is the only object for which attributes are computed (through [patcherargs]) after [loadbang], which makes it quite unsettling when we built new abstractions that need initialization through attributes to be done before loadbangs, just like every other objects.

The only workaround I found is to put a [deferlow] between the [loadbang] and the sub[patcher] :(

Max Patch
Copy patch and select New From Clipboard in Max.



Roman Thilenius's icon

that [route a b c] example is even more strange than the patcherargs object itself and the attempt to use it with [patcher].

as it seems, the runtime can not load the "object box" from the json "without its content", so i believe you needed change your practice beginning new abstractions as subpatcher, and instead create a file first.

(there are additional reasons to do so. for example when i just pasted the patch, it also did nto initialize and i get no bang outptu at all. there are a few other thigns which also work better in any situation when the subpatcher is a file.)

patcher always was a bit special, and if it was made for using arguments it would probably accept those directly and not require an attributes workaround. :)

TFL's icon

that [route a b c] example is even more strange than the patcherargs object itself and the attempt to use it with [patcher].

What you mean by that? Here the [route] acts for both patherargs and what's coming from the inlets, so you can address attributes to that patcher just like with most other objets (set the default value of an attribute by typing it in the object's box, and change that value when the patch runs by sending a message "attributename value").

As for abstrations as .maxpat patcher files versus embeded patcher: they behave the same in terms of what is processed first between patchargs and loadbangs. I actually first encountered this behaviour with file based abstraction. I used and embeded patcher just for the sake of the example.
I should have precised that you need to save the patch as a file after pasting it, then close it and open it to get what I mean. I though it was mandatory as we were talking about loadbangs.

What should be your best practice when it comes to create patcher abstractions that could be initialized just like other objects?

Roman Thilenius's icon

the more i explain the more unclear i become. :(

let my try again.

the difference between #1 and patcherargs is known:

p foo does not support #1, so you use patcherargs.

but patcherargs loads after the motherpatch, so now you try to use attributes instead of arguments.

for attributes it also does not work, so you now try to use defer.

i recommend to make abstractions instead, so that you can use #1 and have full control over order.

TFL's icon

WOW you just made me discover a new old Max feature. Where is that documented?? (answer to myself: here). Can't believe I missed it. I knew about the #0 becoming a patcher-specific identifier, I knew about $1 $2 in a message object to relate to input list elements, but I didn't know about #1 refering to the patcher's arguments.

For those like me who struggled to get it, here is a more explicit example:

This is super handy but the main downside is that it becomes quite cumbersome if you want to work with a lot of arguments (remember which is which...) and not always declaring all of them and falling back to some default values instead.

I'll keep this in mind but in my specific use case I'll stay with patcherargs and deferlow for now!

EDIT: okay, by reading the documentation i found out that you can stick a name to an argument (eg. #1-special becomes 'hollidays-special' if the patcher's first argument is 'hollidays'), but still not as convenient as attributes.

tyler mazaika's icon

Tutorial 15: Abstractions --> Using an abstraction with replaceable arguments.

I guess I don't know how people learn Max these days, but I definitely went through all the tutorials in order back in 2006. The ordering is interesting, though, as I don't remember any drawing/video tutorials (currently # 9-13) prior to abstractions.

TFL's icon

Thanks to point this out.
To me there is now way I could learn Max linearly. I did most of the tutorials (like 6 years ago), but there was some stuff I did not get right yet, then you work on a project needing a specific area of Max, and kinda forget about some of that earlier stuff. There's a lot of details to remember and those you don't work regularly with, you just forget them. At least to me this is how it works. You can end up proficient with all the jit and jit.gl world but not being capable of making a basic audio synth without re-reading a lot and looking at examples.
Anyway, why [patcherarg] is treated after [loadbang] still looks like a design mystery to me, but now I have some workaround.

Vincent Goudard's icon

@roman: it's not so much the poundsign that makes the difference in your example, but in fact the loadbang, that fires indeed before the parent patcher's loadbang. But you could as well loadbang the patcherargs and it would output its values, without being limited by the range of poundsign values (#1 to #9), or being prevented from using a variable number of arguments.

The main drawback then is that you would need to prevent these patcherargs value to be output again at patcherargs's own auto-firing time (for instance, using closing gates after patcherargs's done message). Definitely do-able though.

But then you'll have the problem that pattr and parameter_enabled objects fire their init values even before the loadbangs...

In short, I would too enjoy it when patcherargs are triggered before anything else, so that they could be used as constructors, as mentionned in the OP, but instead, they trigger last. :(

I'm afraid this might be much too late to change this behaviour in Max, but who knows?

In the meantime, the best option might be not to use any loadbang at all. How rad is that? Maybe less rad than Roman using Max3.x in 2023!

If someone has better option, I'd be interested to know!

Roman Thilenius's icon

f***, i just hit the delete button by accident. second service.

loadbang made "patcherargs" possible before the compliled external even existed and i see no benefit in the object for most situations.

with mr. loadbang you can create abstraction patchers which perform 100% like compiled externals. you always see loadbang, and it always serves you the desired load order.

btw. here is a simple trick for everyone who has the same problem with [patcherargs] as the threadstarter: you can use dspstate~ to find out when audio starts: when audio starts, we know that object- and patch-initialisations are finished. now use "audio is on" to trigger the loadbang in your root patcher.
using defer ist not enough. loadbang does not even run in the high priority.


Nodanoma's icon

Perhaps I missed it in the previous comments, but the simplest answer to the initial question is probably: send a loadbang straight into patcherargs for the arguments/attributes to spread upon object initialisation. The really only snag is that patcherargs will antively fire again once the parent patch is loaded, but this may or may not be a problem.

I use patcherargs every time when creating new objects and tend to document the object's attributes and methods in a maxref.xml along with a helpfile while I remember. Handling objects with atributes in the object box is 100% convenient, even if abstractions don't expose their attributes to an attrui, as opposed to externals.

I am in fact really appreciative of this object.

Fun fact, not only relating to patcherargs (toung twister by now): you can cascade even #0-arguments down nested abstractions, inheriting them as numbered pound-signs as you go down the line. This way you can manage individual namespace across nested abstractions.