An example of Pd's data-plus-accessor arrangement is that maintained by
floating-point arrays (either graphical or via the
table object), and
the suite of objects
tabwrite, and all their relatives.
For example, Figure 3 shows how to use accessor objects to increment a variable
element of an array (you would do this to make a histogram of incoming indices,
for example.) Here the task is straightforward, and the separation of the
storage functionality of the actual ``array1" from the accessor objects is not
Moving to a more interesting case, we now build a patch to do something corresponding to this using the (still experimental) ``data" feature of Pd [Puc02b]. For completeness we give a short summary here, which will serve also to introduce the central example of this paper.
Pd's ``data" are objects that have a screen appearance; many such objects can be held in one Pd canvas. The canvas holds a linked list of data. A datum belongs to some data structure, which is defined by a patch called a template. The template also defines how the data will look on the page. Lists of data are heterogeneous; a canvas in Pd can hold data with many different structures. Figure 4 shows a canvas with three data objects. They belong to two types: two triangles and one rectangle.
As data structures, this list could appear as shown in Figure 5. The elements of the list need not all have the same structure, but they have a ``class" field that determines which of the several possible data structures the element actually belongs to.
The data structures are defined by
struct objects. Figure 6 shows the
struct object corresponding to the triangles in Figure 4. The canvas
struct object may also contain drawing
instructions such as the
drawpolygon object. This object takes three
creation arguments to set the interior and border colors and the border width
(999, 0, and 2), and then any number of (x, y) pairs to give vertices of the
polygon to draw; in this example there are three points and the structure
h gives the altitude of the triangle.
For clarity, and for the sake of comparison, we'll consider C and Pd approaches
to defining and accessing the data in parallel. In C, the definitions of the
two data structures might be as shown in Figure 7. In order to be able to mix
the two structures in a single linked list, a common structure sits at the head
of each. This common structure holds a
whichclass field to indicate which
structure we're actually looking at, and a
next field for holding a
collection of these structures in a linked list.
Now we define a task that might correspond to that of Figure 3. Suppose, given
an integer and a linked list of data structures, we wanted to find the
th occurrence of
struct1 in the list and increment its
slot. (Note that incrementing the
h slot of an instance of
class2 wouldn't make sense.) A C function to do this is shown in Figure
8. This is an inherently more complicated problem than that of Figure 3;
there, a corresponding piece of C code might simply be:
array[n] += 1;Instead, we have to make a loop to search through the heterogeneous list, checking each one if it belongs to
struct1, maintaining a count, and when all conditions line up, incrementing the
An equivalent Pd patch is shown in Figure 9. The loop is managed by the
until object. The top
trigger initializes the
pointer objects (corresponding to ``count" and ``ptr" in the C
code.) The messages, ``traverse pd-list" and ``next", correspond to the
initialization and update steps in the C loop; the two possible exit
conditions of the loop (the check on ``ptr" and the break in the middle)
are the two patchcords reaching back to the right inlet of the
pointer struct1 object only outputs the pointer if it
matches ``struct1" (corresponding to the first
if in the C code.) The
sel object in the patch corresponds to the check whether ``count" and
``n" are equal in the C code. The remainder, below the second
object, is much the same as in Figure 3.