On Sat, 7 Feb 2009, Claude Heiland-Allen wrote:
I don't know why, but it makes parsing Pd patches 1000x less straightforward than required (you need a two-phase parser that has a special exception to detect message boxes and not expand dollars, allowing the message box objects to parse them itself later, while expanding dollars for everything else).
The way it works in Pd, Is that the parsing only cuts a patch into lists of atoms, and then the evaluation of $ is a separate phase. There are two levels of evaluation of $ in patches: one is because the patch is saved as a sequence of messages that do dynamic patching of all of the patch. Therefore, an objectbox containing $0 has to be saved as $0, which gets converted to $0 on the first evaluation, and the $0 turns into a float on the second evaluation.
I don't think that this way of doing things is really bad, except perhaps that it allows one to make patches that do weird things that don't get saved back the same way (e.g. what if you edit a .pd file to put non-backslashed dollars in it?)
That #X obj has this extra evaluation level compared to #X msg and others, is not necessarily bad nor uncommon. The LISP languages generally have that: there are a number of so-called special-forms in which arguments are not evaluated, and some others in which only some arguments are evaluated. This is how 'foo is a shortcut for (quote foo) in which the argument of quote is not evaluated. In theory, you only really need that one special-form in such a language, but the inventors of this figured out that it was annoying to have to have only one special-form because it needs too many apostrophes all over the place. In the end, though, inventors of various LISP dialects could not agree on how many special-forms there should be. (Macros allow the user to define its own things that look like special-forms, but because of their evaluation order, it also allows bypassing any non-evaluation too)
In Tcl, which is a distant cousin of LISP, things are different. Instead, there is an extra level of syntax because all lists are assumed to be quoted, a first parsing handles only { } { } and a second parsing handles $ $ [ ] [ ] ... not counting the [expr] calls, which are a third level of parsing and happens quite often because it's explicit in [if] [while] etc. The avoidance of having some kind of evaluation at the first level of parsing makes it necessary to have the second level. My point is that it's a tradeoff in the design of languages. If you remove complexity in one way, it reappears in another way if the complexity is necessary.
So, what could have Pd done differently? Perhaps two things:
backslashes aren't needed in the file format.
message arguments are substituted using # or whatever (that's a second level of parsing because # is not recognised at the first parsing level; or would it??). But this makes people want to use $ to access abstraction-args directly in it, and if that feature is considered as a good thing, then you still need to either skip substitution in #X msg by opposition to #X obj, or add another level of backslashes in msg.
(But that's all very hypothetical and nothing of that will change in pd)
I ran into this problem implementing PotatoData (basically a proof of concept, it's a Pd patch interpreter written in Lua with minimal amounts of C for DSP, can run some trivial audio patches) a couple of months ago, and just ducked it completely - message boxes in my implementation don't support dollars at all (nor commas or semicolons for sequencing and redirection, but that's a separate issue). I wish message boxes had used a different special character, it would have made life much much easier.
I don't think it's a big deal. There are much more difficult things than that, that you have to do to make a good interpreter and/or compiler. It's just a bit confusing and somewhat easy to get wrong if you don't put all of your attention in it, but if pd were different, this set of problems would be replaced by another set of problems.
It's a mess. There are two similar concepts at work:
- replacing dollars with arguments at patch execution time
- replacing dollars with arguments at message passing time
There are three of them. 0. replacing dollars when loading patch (not normally used)
The confusion arises partly because when Pd loads a patch, it's really internally passing messages around.
That's why level 0 is there. It's never used by normal patches, yet it makes it necessary to add extra backslashes everywhere.
Perhaps all this Pd parsing process is more difficult because it is not so well documented (or the documentation has been forgotten in some dungeon and is not part of any manual). Therefore you have to discover more of it yourself and may have surprises and there are not many people paying attention to the topic and not much standard terminology to talk about how it is done in Pd. It doesn't *have* to be simplified, it has to be seen as simpler. But in any case, things become seen as simpler once they are understood.
$ in message boxes is unfortunate. If there was a different symbol, perhaps #, you could combine both phases in one object box to avoid jumping through pointless hoops.
exactly. well, it's very well possible to just avoid using messageboxes and instead use an external that would do the same job. It's not so hard.
[$0-#1-$2-#3( would be nice, but as Pd is now, it's a nightmare.
What about [m $0-#1-$2-#3] ? if such an external existed... the only funky thing in there is if $2 substitutes to something with a "#" in it... in that case, the extra level of evaluation would become apparent.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec