Dear list,
I just ran into something very odd while trying to parse a string to extract a filename from a path with [list fromsymbol]. Please look at the patch attached. I try to loop backward through the fields of a line in a [text] object to find the first "/" (code 47).
When I do it "manually" (load the list and get the last field, then decrease the counter with a bang until I reach the last "/", everything works fine, and the counter starts at 17 and goes down.
But when I try to automate it by checking if the output equals 47 and by sending a bang to my counter when it's not, I get a very strange result. The counter actually starts at the last occurrence of "/" (47) in field 8, and then goes up to 17.
I am probably very tired and I must be missing something obvious. But right now this looks like aliens have hacked into Pd and are playing with my nerves.
Thanks in advance for your help, Pierre.
PS : I've been using the new text and array objects and I think they're very useful, though not always super intuitive.
On 2015-06-02 23:10, Pierre Massat wrote:
I am probably very tired and I must be missing something obvious. But right now this looks like aliens have hacked into Pd and are playing with my nerves.
afaict¹, you are violating the first rule of patching:
*never* do a fan-out without a trigger. *always* use a trigger if you want to connect a single outlet with multiple inlets. *always*.
fgmasdr IOhannes
¹ i was pretty sure that this would be the answer before i looked at your patch; it usually is; but this also means that i'm very biased and might have missed something else.
You need to trigger the print before the recursion branch.
Because you have the print _after_ the recursion branch, the prints can only get triggered after the complete recursion has stopped.
That's why the output is reversed in order.
Take a look at pd manual: 2.3.2. depth first message passing
Cheers, jan
On 06/02/2015 11:10 PM, Pierre Massat wrote:
Dear list,
I just ran into something very odd while trying to parse a string to extract a filename from a path with [list fromsymbol]. Please look at the patch attached. I try to loop backward through the fields of a line in a [text] object to find the first "/" (code 47).
When I do it "manually" (load the list and get the last field, then decrease the counter with a bang until I reach the last "/", everything works fine, and the counter starts at 17 and goes down.
But when I try to automate it by checking if the output equals 47 and by sending a bang to my counter when it's not, I get a very strange result. The counter actually starts at the last occurrence of "/" (47) in field 8, and then goes up to 17.
I am probably very tired and I must be missing something obvious. But right now this looks like aliens have hacked into Pd and are playing with my nerves.
Thanks in advance for your help, Pierre.
PS : I've been using the new text and array objects and I think they're very useful, though not always super intuitive.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
Thank you both very much for the explanations. So if I got it right, the loop in itself was behaving as expected, but what was being printed in the console was not reflecting that. Instead print behaved like a list prepend. That's good to know, I candidly thought that print objects were printing out stuff in real time irrespective of what was going on in the rest of the patch.
Cheers,
Pierre.
2015-06-03 19:47 GMT+02:00 Jan Baumgart raga.raga@gmx.de:
You need to trigger the print before the recursion branch.
Because you have the print _after_ the recursion branch, the prints can only get triggered after the complete recursion has stopped.
That's why the output is reversed in order.
Take a look at pd manual: 2.3.2. depth first message passing
Cheers, jan
On 06/02/2015 11:10 PM, Pierre Massat wrote:
Dear list,
I just ran into something very odd while trying to parse a string to extract a filename from a path with [list fromsymbol]. Please look at the patch attached. I try to loop backward through the fields of a line in a [text] object to find the first "/" (code 47).
When I do it "manually" (load the list and get the last field, then decrease the counter with a bang until I reach the last "/", everything works fine, and the counter starts at 17 and goes down.
But when I try to automate it by checking if the output equals 47 and by sending a bang to my counter when it's not, I get a very strange result. The counter actually starts at the last occurrence of "/" (47) in field 8, and then goes up to 17.
I am probably very tired and I must be missing something obvious. But right now this looks like aliens have hacked into Pd and are playing with my nerves.
Thanks in advance for your help, Pierre.
PS : I've been using the new text and array objects and I think they're very useful, though not always super intuitive.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
-- Jan Baumgart Technischer Mitarbeiter Hochschule für Musik und Darstellende Kunst Eschersheimer Landstr. 29-39 60322 Frankfurt am Main
On 06/03/2015 09:40 PM, Pierre Massat wrote:
Thank you both very much for the explanations. So if I got it right, the loop in itself was behaving as expected, but what was being printed in the console was not reflecting that. Instead print behaved like a list prepend. That's good to know, I candidly thought that print objects were printing out stuff in real time irrespective of what was going on in the rest of the patch.
no. everything was behaving as expected, and [print] was printing in "real time" (whatever that means).
but time in Pd is a fickle thing, and while things can happen in zero-time they also happen one after the other. [print] immediately prints any data it receives, but your patch was made in a way that would send the "last" message to [print] before it would send the "first" message. hence the reversion.
to re-iterate: [trigger] would have made this more obvious.
gfmsd IOhannes
On 06/03/2015 05:03 PM, IOhannes m zmölnig wrote:
On 06/03/2015 09:40 PM, Pierre Massat wrote:
Thank you both very much for the explanations. So if I got it right, the loop in itself was behaving as expected, but what was being printed in the console was not reflecting that. Instead print behaved like a list prepend. That's good to know, I candidly thought that print objects were printing out stuff in real time irrespective of what was going on in the rest of the patch.
no. everything was behaving as expected, and [print] was printing in "real time" (whatever that means).
but time in Pd is a fickle thing, and while things can happen in zero-time they also happen one after the other. [print] immediately prints any data it receives, but your patch was made in a way that would send the "last" message to [print] before it would send the "first" message. hence the reversion.
to re-iterate: [trigger] would have made this more obvious.
But the author of the patch was under the impression that the firing order didn't matter. In cases like this [trigger] won't help-- the user would still have the same 50% chance of making the connections in the wrong order.
If you meant that it would have made the error more obvious to *you*, well... it's hard to beat the speed of proclaiming a rule without even looking at the patch. If the author had slavishly employed [trigger] in place of fan-outs with the same bad luck as their fanout ordering, then your proclamation wouldn't have applied in this case. (And fanouts are more obvious than [trigger] objects wired in the wrong order, and especially where recursion is involved.)
So I'd say use fanouts where ordering doesn't matter, but keep an eye on them and make sure they _still_ don't matter when you need to debug.
Otherwise you'd end up mindlessly inserting/removing a bunch of [trigger] objects just for debugging stumps (like [print] and number box). With GUI software like Pd Vanilla that doesn't have infinite undo your hand will get tired and you'll have to rest. That probably eats at least much time as you'd save avoiding potential fanout bugs.
-Jonathan
gfmsd IOhannes
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On 04/06/15 08:03, Jonathan Wilkes via Pd-list wrote:
On 06/03/2015 05:03 PM, IOhannes m zmölnig wrote:
On 06/03/2015 09:40 PM, Pierre Massat wrote:
Thank you both very much for the explanations. So if I got it right, the loop in itself was behaving as expected, but what was being printed in the console was not reflecting that. Instead print behaved like a list prepend. That's good to know, I candidly thought that print objects were printing out stuff in real time irrespective of what was going on in the rest of the patch.
no. everything was behaving as expected, and [print] was printing in "real time" (whatever that means).
but time in Pd is a fickle thing, and while things can happen in zero-time they also happen one after the other. [print] immediately prints any data it receives, but your patch was made in a way that would send the "last" message to [print] before it would send the "first" message. hence the reversion.
to re-iterate: [trigger] would have made this more obvious.
But the author of the patch was under the impression that the firing order didn't matter. In cases like this [trigger] won't help-- the user would still have the same 50% chance of making the connections in the wrong order.
Surely that confusion, and it is a common one, is not understanding properly what is being drawn when writing a pd patch, it is very important to understand that it is a depth first tree and a single iterative process run once each dsp block. Fanouts are ambiguous and obfuscate this critical aspect of pd, they suggest a kind of parallel implementation of dataflow which is not correct.
Sure, after this is fully understood then fanouts are a convenient shortcut when you know that the ambiguity is not important, and when you consistently read them as ambiguous triggers ... but too often they are used without understanding this, hence they are dangerous, hence the very sound advice to replace them with triggers (and consider carefully the choice of order) when a patch is not doing what you think it should. Hence also any beginner should be taught not to use fanouts until they are well familiar with the language.
Simon
On 04/06/15 06:03, Jonathan Wilkes via Pd-list wrote:
(And fanouts are more obvious than [trigger] objects wired in the
wrong order, and especially where recursion is involved.)
I am confused by this assertion. Can you explain like I am five?
Probably my failing but I am unable to imagine a situation in which "fanouts are more obvious than [trigger]" and I don't understand the qualifier "especially where recursion is involved". How do you define "obvious" as used here?
Last night I spent several hours tracking down a bug that turned out to be because I had used a fan-out instead of a trigger. I am not 100% sure if this backs up your point or refutes it but either way it sucked. :)
I think I will continue to try and make myself use trigger objects instead of fan-outs to avoid that type of bug again.
Cheers,
Chris.
Dear all,
Just to give you my modest input on this discussion. I just looked at IOhannes' last patch and now I got it. The mistake I made was to believe that print would send the current value to the console at each step of the loop (like print in a for loop in Python for instance), and that the firing order just before the print only mattered at "micro" level. Now of course I understand why I was wrong, after looking up depth first on the web.
I've been using Pd regularly for 7 years now, so I don't consider myself a complete beginner. I use triggers a lot, and only use fan outs when I think the order of events is not critical. For 7 years I've believed that triggers only worked at "micro" level to sequence events that are on the same "level". Of course now I know that this assumption was completely wrong, and if I had tried harder to understand how events are sequenced at "macro" (whole tree) level this would have been obvious.
Honestly I think that this particular problem should be explained much more clearly in the manual, in the depthfirst example file, and perhaps in the trigger help file. I wonder how many people in the pd-list would make the same mistake.
Anyway, than you again for your enlightening responses.
Pierre.
2015-06-04 8:11 GMT+02:00 Chris McCormick chris@mccormick.cx:
On 04/06/15 06:03, Jonathan Wilkes via Pd-list wrote:
(And fanouts are more obvious than [trigger] objects wired in the
wrong order, and especially where recursion is involved.)
I am confused by this assertion. Can you explain like I am five?
Probably my failing but I am unable to imagine a situation in which "fanouts are more obvious than [trigger]" and I don't understand the qualifier "especially where recursion is involved". How do you define "obvious" as used here?
Last night I spent several hours tracking down a bug that turned out to be because I had used a fan-out instead of a trigger. I am not 100% sure if this backs up your point or refutes it but either way it sucked. :)
I think I will continue to try and make myself use trigger objects instead of fan-outs to avoid that type of bug again.
Cheers,
Chris.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On 06/04/2015 04:03 AM, Pierre Massat wrote:
Dear all,
Just to give you my modest input on this discussion. I just looked at IOhannes' last patch and now I got it. The mistake I made was to believe that print would send the current value to the console at each step of the loop (like print in a for loop in Python for instance), and that the firing order just before the print only mattered at "micro" level.
This is actually a great example of what I was talking about with dogmatic use of trigger vs fanouts.
It sounds like Pierre was thinking that trigger would fire "breadth-first" before starting the next iteration of the loop. If he had employed a trigger in this example, he was under the impression that [print] would fire each iteration regardless of which outlet of trigger it was hooked to. He thought he could put the [print] before OR after the connection triggering the recursion.
So even with a dogmatic use of trigger, Pierre would have had a 50% chance of hitting the bug. And that's the same chance he had by using the fanout.
Because he did use a fanout, IOhannes' proclamation to never use them guided him quickly to the problem. The irony is if he had used a dogmatic trigger and hit the bug, it would have taken him longer to find since they are indistinguishable from normal triggers.
-Jonathan
Now of course I understand why I was wrong, after looking up depth first on the web.
I've been using Pd regularly for 7 years now, so I don't consider myself a complete beginner. I use triggers a lot, and only use fan outs when I think the order of events is not critical. For 7 years I've believed that triggers only worked at "micro" level to sequence events that are on the same "level". Of course now I know that this assumption was completely wrong, and if I had tried harder to understand how events are sequenced at "macro" (whole tree) level this would have been obvious.
Honestly I think that this particular problem should be explained much more clearly in the manual, in the depthfirst example file, and perhaps in the trigger help file. I wonder how many people in the pd-list would make the same mistake.
Anyway, than you again for your enlightening responses.
Pierre.
2015-06-04 8:11 GMT+02:00 Chris McCormick <chris@mccormick.cx mailto:chris@mccormick.cx>:
On 04/06/15 06:03, Jonathan Wilkes via Pd-list wrote: > (And fanouts are more obvious than [trigger] objects wired in the wrong order, and especially where recursion is involved.) I am confused by this assertion. Can you explain like I am five? Probably my failing but I am unable to imagine a situation in which "fanouts are more obvious than [trigger]" and I don't understand the qualifier "especially where recursion is involved". How do you define "obvious" as used here? Last night I spent several hours tracking down a bug that turned out to be because I had used a fan-out instead of a trigger. I am not 100% sure if this backs up your point or refutes it but either way it sucked. :) I think I will continue to try and make myself use trigger objects instead of fan-outs to avoid that type of bug again. Cheers, Chris. -- http://mccormick.cx/ _______________________________________________ Pd-list@lists.iem.at <mailto:Pd-list@lists.iem.at> mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On 06/05/2015 04:55 AM, Jonathan Wilkes via Pd-list wrote:
It sounds like Pierre was thinking that trigger would fire "breadth-first" before starting the next iteration of the loop.
ah yes. i think i should mention "depth-first" in my scripture answers. thanks.
gfmdsr IOhannes
On 2015-06-04 10:03, Pierre Massat wrote:
The mistake I made was to believe that print would send the current value to the console at each step of the loop (like print in a for loop in Python for instance),
i meant to reply to this, but forgot. i still cannot resist, so:
python actually behaves the same here, as shows the following implementation:
<weirdo.py> def find_slash(counter): char = ord(string[counter - 1]) if char != 47: find_slash(counter - 1) print("output: %s" % (char)) print("counter: %s" % (counter)) counter = counter - 1
string = '/blabla/snare.wav' find_slash(len(string)) </weirdo.py>
but most likely you wouldn't write your python code like that (apart from the fact that in python you would just use "string.rfind('/')")
myself, i would write the code as something like
<noweirdo.py> def find_slash(counter): counter = counter - 1 print("counter: %s" % (counter)) char = ord(string[counter]) print("output: %s" % (char)) if char != 47: find_slash(counter) </noweirdo.py>
which is the same but has the order reversed esp. the recursive call has moved to the very end of the function, *after* all the print() (a common technique to exploit tail recursion optimisation; probably that's the reason why i did it, dunno)
gmfsdr IOhannes
There is one situation where it is ok to use fan outs: and that situation is when you are patching signal objects together. :)
For everything else, use a trigger.
On 06/04/2015 02:11 AM, Chris McCormick wrote:
On 04/06/15 06:03, Jonathan Wilkes via Pd-list wrote:
(And fanouts are more obvious than [trigger] objects wired in the
wrong order, and especially where recursion is involved.)
I am confused by this assertion. Can you explain like I am five?
An Argument Against Dogmatic Triggers
My toolkit:
properly
Your (proposed) toolkit:
doesn't matter but you forced yourself to use trigger anyway
Probably my failing but I am unable to imagine a situation in which "fanouts are more obvious than [trigger]"
If I run into a bug that looks like I screwed up the order of operations, I can start with the fanouts and try to violate my own fanout premise. If I find a part of the patch where order of fanout wires indeed does matter, I instantly know it is the bug and can immediately fix it.
If you run into a bug that looks like you screwed up the order of operations, you can't immediately tell the difference between the triggers that are required to run the patch properly, and the ones that you used merely because you want to avoid the danger of using fanouts (i.e., dogmatic triggers).
Now, you might say that dogmatic use of [trigger] actually forces you to consider the order of operations in a way that my fanouts do not. And that may be true. But inevitably you will end up with a few parts of your patch where you _think_ order doesn't matter. If you use [trigger] in those cases anyway (and choose some arbitrary ordering), you remove the visual evidence that you thought the connection order could be unspecified. If it turns out you indeed chose the wrong order for your trigger, you make it harder to track down that mistake because you cannot tell the difference between your dogmatic triggers and the normal triggers.
and I don't understand the qualifier "especially where recursion is involved".
If I have a choice to debug a recursive (control) object chain using my toolkit vs. your toolkit, I'll choose mine. Because I know to start with the fanouts, and then move to the triggers if I still haven't found the bug. With yours I can't do that because I don't have any visual information about where in the object chain you may have assumed that the ordering of some operations wouldn't affect the function of the patch.
That may sound crazy, except that a) recursion is _really_ awkward and difficult to reason about in Pd and b) Pd _lets_ you make fanouts. If the UI didn't allow fanouts maybe it's a different story. But there are just so many examples in the wild that use fanouts, even fundamental idioms like [f]x[+ 1]. Scripture-style quotations or no, there's just no going back at this point.
So to me, it's more instructive to try to consider which parts of a patch require ordering, which don't, show that in the patch, and think critically about all the above.
How do you define "obvious" as used here?
For example, looking at a patch... *2 seconds of eyeballs doing their thing*... oh, there is the fanout.
vs...
Oh, _everything's_ a trigger. Thinking... *2-2000 seconds of thought*... oh, there is the dogmatic trigger.
There are of course other types of bugs, but that's the comparison for wire-ordering bugs.
Last night I spent several hours tracking down a bug that turned out to be because I had used a fan-out instead of a trigger. I am not 100% sure if this backs up your point or refutes it but either way it sucked. :)
I think I will continue to try and make myself use trigger objects instead of fan-outs to avoid that type of bug again.
I think the more you consider the consequence of how things are ordered in Pd, the easier it will be to track down bugs.
You might still achieve that by dogmatic use of trigger. But I think it's counter-productive to make proclamations against a feature that the UI allows, _and_ that everyone including the original author uses in every non-trivial patch.
-Jonathan
Cheers,
Chris.
On 05/06/15 10:24, Jonathan Wilkes wrote:
On 06/04/2015 02:11 AM, Chris McCormick wrote:
On 04/06/15 06:03, Jonathan Wilkes via Pd-list wrote:
(And fanouts are more obvious than [trigger] objects wired in the
wrong order, and especially where recursion is involved.)
I am confused by this assertion. Can you explain like I am five?
An Argument Against Dogmatic Triggers
Ok, I understand now. Yep, that makes a lot of sense. Thanks for taking the time to explain!
Cheers,
Chris.
On 06/04/2015 11:13 PM, Chris McCormick wrote:
On 05/06/15 10:24, Jonathan Wilkes wrote:
On 06/04/2015 02:11 AM, Chris McCormick wrote:
On 04/06/15 06:03, Jonathan Wilkes via Pd-list wrote:
(And fanouts are more obvious than [trigger] objects wired in the
wrong order, and especially where recursion is involved.)
I am confused by this assertion. Can you explain like I am five?
An Argument Against Dogmatic Triggers
Ok, I understand now. Yep, that makes a lot of sense. Thanks for taking the time to explain!
Also-- I like reserving dogma for the places where it truly is inviolable. IOhannes' "scripture" quote against assuming that TCP will format data according to message boundaries is a good example. One who makes that assumption _will_ suffer the wrath of Kahn.
-Jonathan
Cheers,
Chris.
On 06/05/2015 04:24 AM, Jonathan Wilkes via Pd-list wrote:
If I have a choice to debug a recursive (control) object chain using my toolkit vs. your toolkit, I'll choose mine.
totally. i very much prefer your toolkit as well, as it allows me to blindly answer the question "why is my patch behaving weirdly?" with a "there's a fanout that makes your patch do something that you cannot see by tracking the connections", and i get another 20+ points on stackoverflow (and probably another 10- points for becoming an unbearable evangelist)
the above paragraph contains a key element that i (try to) teach my students when it comes to understanding how a given patch works: take your finger and visually track how the messages travel through all the connections in a depth-first order. i found that this only works when you have (dogmatic or not) triggers.
fgadsmr IOhannes
On 06/05/2015 04:24 AM, Jonathan Wilkes via Pd-list wrote:
For example, looking at a patch... *2 seconds of eyeballs doing their thing*... oh, there is the fanout.
vs...
Oh, _everything's_ a trigger. Thinking... *2-2000 seconds of thought*... oh, there is the dogmatic trigger.
thanks for sharing your thoughts.
your numbers are pretty impressive, but i'm still unconvinced though.
in my experience, i have encountered case#1 countless times, whereas i haven't seen case#2 *ever*, which makes:
(that's quite some time)
much time)
chances are, that when everybody had adopted my dogmatic use of [trigger], case#2 could eventually be seen in real life. until then, i might continue to preach the one true whatever.
gfmdsar IOhannes
On 06/02/2015 11:10 PM, Pierre Massat wrote:
PS : I've been using the new text and array objects and I think they're very useful, though not always super intuitive.
btw, is there a reason to not use [table] (or [array]) to store numbers? it seems that [text] is a total overkill. a quick test also seems to indicate that [tabread] would be almost 10 times as fast.
gfmadr IOhannes
Dear all,
Sorry I forgot to reply. Thank you all for your inputs. I've learned something. @IOhannes : I've used an array instead as suggested.
Cheers,
Pierre.
2015-06-10 17:15 GMT+02:00 IOhannes m zmölnig zmoelnig@iem.at:
On 06/02/2015 11:10 PM, Pierre Massat wrote:
PS : I've been using the new text and array objects and I think they're very useful, though not always super intuitive.
btw, is there a reason to not use [table] (or [array]) to store numbers? it seems that [text] is a total overkill. a quick test also seems to indicate that [tabread] would be almost 10 times as fast.
gfmadr IOhannes
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list