Design Philosophy of Max/MSP
If I am uneducated on this topic, please do enlighten me with links to interviews, papers, talks, podcasts, discussions etc! I am a vessel open to learning.
I used Max/MSP in university alongside Puredata, as a younger person, and found it great fun and a source of lots of interesting projects and experiments in building digital tools. However - I will admit I never quite made it past the "hack and slash" approach of trying things until they worked, and pulling out pieces of working constructs to frankenstein together whatever goal I was trying to achieve.
Fast forward 15 years or so, and I now work in code as a primary source of income, and have a more robust familiarity with the design principles of programming languages generally... arguments, functions, objects, return values, etc.
Returning to Max/MSP in this context, I am perplexed by some of the choices made in implementation of objects. Specifically, I don't really understand why some objects have multiple inputs, and why some inputs accept a plurality on incoming argument "types", from specific keyword strings, to integers, to boolean values, or even incoming audio streams.
My specific example is sfrecord~. Is there a design choice rule which decides that only two inputs will be used, and that the 2nd one will accept only the 2nd of a pair of audio input streams, while the first input will accept keyword args, a 0/1 integer pair, and audio input streams? It seems a little odd, and i just don't quite grok the design choice behind it, if there is one. I would like to understand better, as I return to and slowly begin relearning Max/MSP, because I find that being able to model a structured behaviour throughout a system can be extremely useful in growing to understand it in an organic way.
So basically - why so many argument types to one input? Why not several dedicated inputs, one per input "type"... and as a follow up, does the latter behaviour pop up in other objects or is it a general rule that input number 1 accepts "any and all inputs including control inputs" and any necessary "extra" inputs get spread out along the objects length?
Thank you in advance.
not sure if it is possible to point out a specific reason, but we can try guessing a few.
1.
for example there are many objects with only one input. a design where the first inlet only takes bangs, the second only numbers and the third only lists would not work for those. there are also objects with a dynamic number of inputs.
if you only distribute stuff around where possible, objects would work differently.
2.
there are situations where "start", "4.5" and "mode 3" are coming from the same source object. do you really want to make 3 connections between these objects?
3.
for a number of reasons the majority of inlets would still have to do a type check even if they would only take one data type. so here is nothing which could be saved.
your example sfplay~ only has a second input because it allows a signal for the speed. moving the number input for the speed to the same inlet seems only consequent.
that dac~ allows 0/1 to be sent to either of its inlets is not consequent; that one is against the rules.
Much of it also has to do with the concept of hot and cold inlets, and the general way event ordering works in max. For example, a plus box can take either a value in the right inlet to set one operand and a value in the left to set the other operand and trigger the calculation, or a two-item list in the left inlet. If there was a dedicated list inlet, would that be a hot or cold inlet? If hot, then do you have two hot inlets? That would be extremely confusing. I think the logic of it (which does have its failings, see below) has more to do with convenience of patching than something that would feel consistent from an informatics point of view.
In a case like sfrecord~, I suspect the design choice of having the left inlet accept both audio and messages was simply to avoid excessive numbers of inlets if that can be avoided -- a decision that makes perfect sense in terms of trying to minimize patch clutter, which is also a design choice.
Also, Max has been developed over four decades now by dozens of people, and the very idea of what the program should be has also changed over that time. Why does [counter] have a dedicated inlet for maximum count, but you have to send a message for minimum count? It made sense to someone at some point, back when Max was a MIDI-only program with a user base of 40 people. Why is it still that way? Because a great deal of care has been taken to maintain backwards compatibility -- I can open I patch I wrote 30 years ago in Max 2.5, and it will run fine, so one can't really be messing with inlet/outlet counts for example, even if it isn't strictly 'consistent'.
The introduction of attributes, and their incorporation by an increasing number of 'legacy' objects also serves the design goal of patching simplicity. All of our lives were changed by being able to make [random @range 2 8] rather than messing with a plus box to offset the low value, but if you added an inlet to do the same thing, you would break a million patches...
hope this shines some light....
\M