[PD] [list] output

Matteo Sisti Sette matteosistisette at gmail.com
Fri Feb 5 19:56:49 CET 2010


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.

1) The "float" or "list" identifiers are implicit when a message starts 
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.

2) One-element lists are equivalent to symbols or numbers, depending on 
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(

3) Equivalent means that ALL objects in Pd will treat such messages 
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.

4) A "bang" is equivalent to an empty list, so

  [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.

5) [route] has a peculiar behaviour, fairly well defined, perhaps less 
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:

   - When the identifier of the message, other than "list", "float", 
"symbol", "bang", is matched, it is stripped. For example:

    "foo bar 1 2 3" ->[route foo]-> "bar 1 2 3"

   - No illegal message can be produced, so:
   -- 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"

   - The "float" identifier cannot be stripped
     (or you may say stripping it is identical to leaving it intact 
since "float 1" becomes "1" which is identical to "float 1")

Here comes the (imho) questionable part:

   - The "symbol" identifier WON'T be stripped, but
   - The "list" identifier WILL be stripped
     (when legal, i.e. when the first element is not a float)
   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?


   - finally, when numeric arguments are used and a list starting with a 
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.

6) All [list ...] objects convert any message to a list prior to 
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.


-- 
Matteo Sisti Sette
matteosistisette at gmail.com
http://www.matteosistisette.com




More information about the Pd-list mailing list