[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