[Gridflow-dev] Re: GridFlow workshop (fwd)

Mathieu Bouchard matju at sympatico.ca
Wed May 4 17:32:00 EDT 2005


Here's some doc I had written after the last GridFlow workshop of
University of Ottawa. Unfortunately I still haven't completed it, but I
think that even this part of it will be instructive. It's an elaborated
version of a talk I gave on the 2nd day of the workshop.



---------- Forwarded message ----------
Date: Thu, 30 Dec 2004 04:25:04 -0500 (EST)
From: Mathieu Bouchard <matju at sympatico.ca>
To: Alexandre Castonguay <acastonguay at artengine.ca>
Cc: Nhung Nguyen <nnguy084 at uottawa.ca>, Vitro Bliss <vitrobliss at hotmail.com>,
     Robert Watson <r.r.watson at gmail.com>, Normand Fisher <fishern at ncf.ca>,
     chantal dahan <chantaldahan at yahoo.ca>, pnicastro at artengine.ca
Subject: Re: GridFlow workshop


On Wed, 22 Dec 2004, Alexandre Castonguay wrote:

> Mathieu may want to send us more details or docs and conversely you
> might have questions for him during the break so here is the email
> list from the wkp. It was nice to see familiar and new faces.  I hope
> that everyone got something out of it.  I know I was intrigued by the
> ease with which new objects can be declared in GridFlow / ruby.

Alright. So here's a summary for you... plus many additional notes. It's
abnormally theoretical/conceptual for something that's workshop material,
but that's my style. The consequence is that a lot of it applies to a lot
more than Ruby and/or Pd.



------------------8<--------cut-here--------8<------------------



1. PureData as a programming language

1.1. PureData is a programming "language". Its status as a language is
debatable because it is visual, which falls outside of the normal
(linguistic) definitions of a language, as the set of possible
sentences and such. However pretty much any file format can be construed
to be a language in some way, and in Pd's case you don't have to construe
it much: a .pd file can be read as a program that does a step-by-step
construction of a patch. There's a command to add an object, another to
add a wire, another to fill a table, another to start a (sub)patch, etc.

1.2. A language is called formal if it is completely defined by precise
grammar rules. Every programming language is a formal language. The Pd
format is a formal language. HTML is a formal language although by itself
it is not a programming language.

1.3. A language is called a programming language when it is universal,
that is, you can describe every possible calculation in it. PureData is
certainly one such thing. Alan Turing and Alonzo Church, in the late
1930's, showed that there are several completely different ways of writing
programs that are equivalent in what they allow to say, as each of them is
proved to be universal. BUT: nothing in that is being said about how easy
it is to express oneself in such a language. The challenge is to find
appropriate models of language for given sets of problems. Several
thousands of programming languages have been invented since (and some of
them are really strange...), and most of them tend to make certain
problems easier.

1.4. PureData is one such thing, that follows a dataflow approach, using
the modular-synthesizer patch-bay metaphor. (Imagine a big Moog... or
even, a manual telephone switch...)



2. the PureData Object Model

(this part contains intertwined concepts that can't be untangled. as a
result, it may be obscure at first read, and become clearer upon
rereading.)

2.1. Programming languages differ vastly by the way their concepts are
organised together. Broad categories of approaches to programming are
called Paradigms (e.g. Dataflow usually counts as a Paradigm; most other
programming languages fall in the Imperative Paradigm). The thing called
Object-Oriented Programming (OOP) is often called a Paradigm too, but it's
more like an aspect that can be adapted to several existing Paradigms.
Usually it's an extension of Imperative Programming; but in the case of
MAX and then PureData, one basic kind of dataflow has been extended with a
dash of OOPness.

2.2. Object: is a thing that receives messages and may emit them. Within
the context of Dataflow, it implies that they go through inlets and
outlets, but other OOP languages don't have these concepts.

2.3. Class: make sure you distinguish between Object and Class. The Class
can be thought of as the set of all possible objects of one "kind". The
Class can also be thought of as the set of behaviours that its objects
will display when being sent messages. So if you write [+ 42] in an
objectbox (where I use [] to mean that it's an objectbox), then "+" is the
name of the class, not the name of the object. An object typically has no
name (though it can be given one sometimes...). At the moment you first
click outside the objectbox, PureData will ask the Class to create an
Object. If you have two boxes of the "+" kind, or even two [+ 42] boxes in
particular, then they are still different Objects, but still the same
Class. User-defined classes are called either "abstractions" if they are
"written" in the Pd language, or "externals" if they are written in some
other language.

2.4. Message: in PureData, those are typically sent from an outlet, along
a wire (aka connection), to an inlet. However, this can be bypassed, but
only for named objects. Some objects have reserved names, some have
definable names called receive-symbols, and there is the [receive] class
(aka just [r]) that make the user choose the name they want. Using Pd
itself you can send through the name system using [send] (aka [s]) or
"send-symbols" or "semicolon-messages". What you type in a messagebox is
not always a message; it may be several; they are comma-separated and will
be sent in that order. In place of a comma, a semicolon may be used, to
say that the next message will also include the name of an object.

Anatomy of a message:

2.4.1. Receiver. It's some kind of destination for the message. In
PureData this part is usually absent and instead determined by looking at
the organisation of outlets/wires/inlets. Else it's always a symbol that
is the name of an object. This contrasts with most other OOP languages
(including Ruby) in which receivers are mandatory (actually they can be
omitted, but when you do so, they default to the "self" object, so you
can't ever say you don't want a receiver. Furthermore, in most OOP
languages (including Ruby again), objects are referred to using pointers
instead of names.

2.4.2. Selector. This is the name of the action to be taken. There's
always a selector in a PureData message, but often it's a default selector
filled in automatically. For example, by trying to send just a lone float,
the selector "float" will be attached to it. Typing several
space-separated things in a messagebox will take the first one as the
selector, but only if it is a symbol. If the first is a float, the "list"
symbol will be used as the selector. The reason for this peculiar
behaviour of PureData is that a selector is always a symbol.

2.4.3. Arguments. Those are often identified by $1, $2, $3, ... in a
messagebox. A message in general may contain any number of arguments
including none at all, but in practice there are some assumptions, like
"float" and "symbol" messages having only $1, and "bang" having none at
all, and "list" having at least a $2 (smaller lists are possible in Pd but
may get automatically transmuted to something else... don't ask me why...)

2.4.4. Atoms. Each argument is an atom, and there are also atoms hidden
inside objects. PureData defines twelve different kinds of atoms, but many
of them are reserved for special purposes (they may be dubbed "magic" or
"radioactive" if you will...) so only three of them are of any
significance to us mere mortals:

 - float
 - symbol
 - pointer

and even then, the latter is rarely used (the curious may consult
pd/doc/7.stuff/data-structures/).

In PureData, it is not possible to create new kinds of atoms yourself, so
in case of GridFlow's grids, full messages are used instead, with the
selector "grid", with $1,$2 identifying the sender (in a non-readable way,
as two floats), with $3 being a code representing the kind of data in the
grid, and any additional arguments being the size of the grid (e.g. $4=240
$5=320 $6=3 is very often used). Usually this workaround doesn't show
much, until you realize you cannot put a grid inside of a list, because
lists only accept atoms, and a message is not an atom.

(end of part 2.4)

2.5. Methods. A method is an action triggered by a message. This depends
on the class of the object. For every class/inlet/selector combination
there may be one method. There may also be a default method for each
class/inlet combination, that picks up any "unknown" selector; that is
usually called a "anything" case or an "A_GIMME". The way the Ruby/Pd
external works is that it only defines a default method for each
class/inlet and it's always the same method everywhere: it's a method that
just translates messages and atoms and then trigger a method on the Ruby
side of things.

(note: in Pd's messagesystem, there's a difference between defining a
first-inlet method, and defining a non-first-inlet one. However, the
Ruby/Pd external conveniently hides this difference.)

2.6. Inheritance. This is when a class is defined using other classes as a
basis. This makes it easy to share many methods between many classes.
PureData doesn't support this feature. It is usually considered required
in definition of OOP, although the OOP languages don't agree at all on how
it's supposed to work. You can only use inheritance with Pd classes if all
of those classes come from the same other language (such as, all classes
are written in Ruby, or all classes are written in Python).

2.7. Polymorphism (of Receivers). This is also considered a required
feature of OOP. It's arguably more important than Inheritance. The idea is
that you don't have to know the class of a receiver to be able to send to
it. There are two basic approaches to this. One is tied to inheritance, as
you can find by learning C++, Java or C#. The other approach is just to
have no restrictions at all; this is the way used by PureData, Ruby,
Python, Scheme, Tcl, Javascript, ...



------------------8<--------cut-here--------8<------------------



Ok, that's it for now. I'll send another mail(s) later for:

  3. Ruby Object Model
  4. Ruby syntax basics
  5. a tour of Ruby's main classes (skipped at the workshop!)
  6. the Ruby-for-Puredata external

And of course, the above "parts 1 and 2" are just part of the bigger
"chapter" on Ruby-based externals.

The two other chapters, the ones about GridFlow's model and Image
Analysis, are both available at http://artengine.ca/matju/graz/ which is
exactly where I picked them up from on the first day. To work, those
patches require GridFlow 0.7.7 (or maybe slightly older) to work. To be
just read, those patches require any roughly recent version of GridFlow,
or PureData 0.38. (note: This is because PureData 0.37 (and former) tend
to do ugly stuff to objects that refer to unknown externals, and i suppose
you don't want that to happen often...)

I can post screenshots of every subpatch of those two chapters, for people
who want to consult them but don't have enough stuff on their computer. I
suppose it would be a bundle of about 14 colour PNG images.

Those screenshots will be created only if one of you wants it.

I can also make them GIF's for those avant-garde people who are already
being retro about the 90's.

_____________________________________________________________________
Mathieu Bouchard -=- Montréal QC Canada -=- http://artengine.ca/matju




More information about the Gridflow-dev mailing list