@oid said:
Because you skipped over learning the basics, objects have hot and cold inlets..,
This idiom, of sending values forward to be stored passively, is critical to successful patching but also seems to be difficult to grasp. Taking myself as example, while I wasn't a CS student, I think I know my way around an algorithm or two, but when I started teaching with Pd, it took me over a year to understand this well.
It's a crucial part of "the basics," but it does take some effort to really get it.
I've thought for a while that Collatz series are a good example of the awkwardness of patching for if-then-else, because a value is used separately in the "then" and "else" branches.
A simple SuperCollider Collatz series function is pretty clear and concise.
(
f = { |x|
while { x != 1 } {
if(x.even) {
x = x div: 2
} {
x = x * 3 + 1
};
x.postln;
}
};
)
The thing that is difficult for patching to handle is that this variable 'x' is referenced in three places, and two of those are conditional -- if 'x' is a patching object, you can't just connect a single [f] box to all of its downstream paths because, in each iteration, one or the other needs to be suppressed.
One way is to set [spigot]s opposite Booleans, and push the value through both of them -- always try to go down both paths, but one of them is blocked.
(
f = { |x|
var cond;
while { x != 1 } {
cond = x.odd;
if(cond.not) {
x = x div: 2
};
if(cond) { // two ifs? hmm...
x = x * 3 + 1
};
x.postln;
}
};
)
Another way is to push the value into separate [f] variables, but bang only one of them.
(
f = { |x|
var trueX, falseX;
while { x != 1 } {
trueX = x; // lol
falseX = x;
if(x.even) {
x = trueX div: 2
} {
x = falseX * 3 + 1
};
x.postln;
}
};
)
And a third way is to mimic [cyclone/gate] by binding the value and the condition together, and using [route] to dispatch.
(
f = { |x|
var bind;
while { x != 1 } {
bind = [x, x.even];
// 'pop' pops from the end,
// similar to [route] popping from the start
if(bind.pop) {
x = bind[0] div: 2
} {
x = bind[0] * 3 + 1
};
x.postln;
}
};
)
All three of these IMO read a bit awkwardly in code (though, using [cyclone/gate] would simplify the third one)... but they're structural necessities in the Max/Pd messaging layer. These are "basics" but not exactly intuitive -- a pedagogical problem.

collatz.pd
hjh