Here we will discuss why $ act differently in object boxes and message boxes.
firstly, some basic things:
dollar signs generally stand for a SUBSTITUTION. It is generally accepted that where there is a dollar sign, that dollar sign will be substituted for another value. That much is true for both objects and message boxes.
The 'special case' is $0. This is a unique identifier that is randomly assigned to your patch. It is a number, usually around 1001~. The purpose of $0 is to give each patch its own identifier; so that, for example, you can open 2 versions of the same patch, and have them both operate separately to each other.
There is another tutorial/explanation i wrote called "what is an abstraction, and why use $0, $1, etc ??", Please go through that FIRST, as it forms a basis for what we will discuss next.
Ok, so now lets get into the nitty gritty of how these $ substitutions differ between objects and messages.
"Object and message boxes are both actually messages, but in the case of the Object box the message is passed at creation time, and for the Message box, at message time."
If you think through that statement carefully enough, it contains nearly everything we need to know here.
Let's break it down:
"in the case of the Object box the message is passed at creation time"
So, if we want to use $ inside objects in an abstraction, then we need to use creation arguments. The exception is $0, which will always be automatically assigned to any abstraction that is used as an object.
for example, if we have an abstraction called "myAbstraction.pd", and if we use it in a patch as [myAbstraction tango bravo 303],
then any Object Boxes inside that abstraction will substitute $1 with the symbol "tango". Likewise $2 will be substituted with the symbol "bravo" and $3 will be substituted with the float 303.
As mentioned before, $0 will be automatically assigned.
Ok, now let's look at the second part of that statement, dealing with $ in message boxes:
"…and for the Message box, (the message is passed) at message time."
This is the vital difference to Object Box use of $. The only way to get values in to a message box is to explicitly pass a message. If we just pass one message into a message box, then we only need to use $1. If we want to pass a list of messages, then we use $1,$2,$3….for as many items that we have in our list.
[$1 red $2(
As should be quite obvious, the $1 is substituted with the float 99, and the $2 is substituted with the symbol "balloons", so our song title is printed as "99 red balloons". (as a side note: if you want to mix floats and symbols like this, then you should always put a float first, otherwise pd gets angry)
please note 2 more important things here:
The creation arguments of our parent patch have NO effect on what happens inside message boxes. Only the message passed into the message box will affect it.
$0 has basically NO meaning in message boxes. $0 would be the "zero-th" item in our list - an pd just always substitutes that for 0. Ideally, i think it would be better if an error were printed to the console instead of this behavior. For all intents and purposes though, there would never be a case when you would want to use $0 inside a message box.
(There are, however, many cases where you would like the use the patch's $0 value inside a message box ... in which case, the $0 value of the parent is passed into the message box as $1 or $2...etc... Please see the example patch for a demonstration of this)
OK, that is pretty much all there is to know. It seems quite simple, and if you follow these basic rules, it really IS simple. The reason why it can appear complicated, is that there are a few occasions when you need to mix up objects and messages, and it's too easy to lose track of which $ do what.
Have a look at the annotated example patch (and abstraction) to see objects and message boxes in action.