Hi,
Maybe I'm late, but I try to answer to the questions that have been raised about the list stuff, for two reasons: first, in case this is helpful to those who asked, and second, so that those who know more than I do can correct me where I'm wrong or show me if the whole thig can be stated in a different way.
This is my understanding of how lists and messages interact.
with a number atom, so
[1( is equivalent to [float 1(
[1 2 3( is equivalent to [list 1 2 3(
Another way of stating this (perhaps more correct??) may be that a message cannot start with a number atom, i.e. it always starts with a symbol atom which is its identifier, so if you type "1" into a message box (or a text file read by [textfile]) the message actually generated has an implicit (or automatically added) "float" or "list" identifier - Which of the two interpretations is more correct is, from my point of view, just an implementation matter.
the type of their only element, so
[list foo( is equivalent to [symbol foo(
[list 1( is equivalent to [float 1( - which is equivalent to [1(
exactly the same way. The fact that some signal objects such as
[*~]
will not accept "list <somenumber>" complaining they have no method for list, is in my opinion a BUG. Somebody just forgot to do the needed conversions at the inlets. I remember someone agreed with me on this.
Whether the conversions are made at outlets or inlets of objects is another implementation matter that I think should be transparent/irrelevant to the user.
[bang( is equivalent to [list(
A message with identifier "bang" _and_ arguments, such as
[bang 1 2 3( or [bang foo bar(
is equivalent to just "bang". At least, [list] objects and [route] treat it as such and ignore its arguments.
well documented, more pragmatical (maybe) than elegant, but pretty consistent, which seems to be:
a. If the arguments are all symbolic atoms, they match the message identifier
b. If the arguments are all numbers, they are interpreted as the first element of a list starting with a number; that is, any list starting with a float that matches an argument, will go out through the corresponding outlet (with the matching float stripped; i'll go into stripping later). Any non-list message will go unmatched.
c. You can use "symbol", "float", "bang" or "list" as arguments of [route]; consistently with what stated at point (a), a symbol (which is a message whose identifier is "symbol") will match the "symbol" argument, etc.
d. Since "symbol foo" and "list foo" are perfectly equivalent messages, it won't matter how you write them, they both mean the same to [route]. So this raises a potential ambiguity: What do you expect to happen with
[symbol foo( | [route symbol list]
? This is both a (one element) list and a symbol. Well, this will match the "symbol" argument (i.e. be output at the first outlet) The same would happen with [list foo(, since it is exactly the same.
Consistently, though surprisingly at first sight, this:
[list foo( | [route list]
will output the list to the "unmatched" (second) outlet, since the message is recognised as a symbol. For the same reason,
[list 1( | [route list]
will go unmatched, since the message is recognised as a float.
That is, "being a float" or "being a symbol" takes priority over "being a one-element list".
This is (i suppose) for the sake of being able to distinguish symbols from floats and from lists. Imagine it wouldn't be so. You couldn't expect [route] to distinguish "list 1" from "1" or "float 1" since this would break the equivalence rules; but then, it would match floats and symbols as lists and you couldn't even distinguish floats from symbols (they would all be one-element lists).
Well maybe it was more obvious than i've made it: the specific takes priority over the general, that's it.
e. If you mix numeric arguments with non-numeric arguments, then the symbolic arguments match a list starting with them as symbol, i.e.
[list foo bar( | [route 1 2 foo]
will match foo, and output "bar" at the third outlet, while
[foo bar( | [route 1 2 foo]
will go unmatched.
I don't think this is documented anywhere and it is rather questionable whether one can expect it... however it is kind of consistent to what it does with floats.
f. This was about matching. Now about the "stripping" behaviour of [route]. Here I do think it has some arbitrary aspects, that is it could behave differently than it does and still be consistent (or even more consistent?), or maybe it's me who don't see the reasoning that make its behaviour the "only consistent possible one" (not that it needs be). Well, here it is:
"symbol", "bang", is matched, it is stripped. For example:
"foo bar 1 2 3" ->[route foo]-> "bar 1 2 3"
-- an empty message will be converted to a bang -- a message starting with a number will become a list (or you may say it already implicitly is)
For example:
"foo" ->[route foo]-> "bang"
"foo 1 2 3" ->[route foo]-> "list 1 2 3" (or "1 2 3" which would be
the same)
"bang" ->[route bang]-> "bang"
since "float 1" becomes "1" which is identical to "float 1")
Here comes the (imho) questionable part:
That is:
"list foo bar" ->[route list]-> "foo bar"
"symbol foo" ->[route symbol]-> "symbol foo"
I personally think that either both or none should be stripped. My personal experience kind of suggests to me that NOT stripping the symbol identifier is probably more desirable (dunnow if it can be "proven" to be so), so I think not stripping the list identifier would be more consistent. Then a simple and general rule could be stated: "All the special identifiers (list, symbol, float, bang) are stripped, while all other identifiers are not"; now you have to exclude list.
I may guess that at some point of history the [list trim] object didn't exist, so [route list] was the only way of stripping a list identifier and converting a list to a non-list?
number is matched, e.g. [1 2 3(->[route 1], both the "list" identifier _and_ the matched first element are stripped, that is:
"list 1 foo bar"->[route 1]->"foo bar", not "list foo bar"
Obviously when the second element is also a float, the list identifier cannot be stripped (or you may say, stripping it is irrelevant). The result is still a list.
performing with it the operations they have to perform. This includes [list length] which indeed once upon a time didn't. That is, [foo 2 3 4(--[list length] gave 3. Now it gives 4, consistently with the rule that the message is converted to a list prior to anything, as with all other list objects. This was a break of backward compatibility (in the case of patches relying on [list length] to count the number of arguments of a non-list message) for the sake of consistency.
I'm not sure exactly where all this information comes from. I think the most part is stated in the "all about data types" patch, or can be somewhat deduced from there; the rest I guess I inferred from tests. I never found any behaviour of Pd that does not match this model, except the abovementioned fact that signal objects (which are supposed to accept floats in their signal inlets), don't accept one-float lists (which are supposed to be equivalent to floats according to this model), and I am not the only one to think this is a bug (note they do accept the one-element list in an inlet if the presence of a float argument converts that inlet to a non-signal inlet)
This whole discussion totally ignores POINTERS (thery are yet another type of atom, aren't they?) because I don't know anything about them. If anybody can fill this gap that would be appreciated (by me at least lol).
Hope this message is of some use.
cheers m.