S+H doesn't work if NIL in Input and spread in Set pin


Maybe it’s a known problem, or a wanted feature, but when a spread is in the Set pin of S+H, NIL can go through S+H even if Set is null. This doesn’t happen (as wanted according to me) when a single bang/toggle is in the Set pin.
See the patch if I’m not clear.

I’m using beta45.0


BugS+H.v4p (9.6 kB)

uh, i’m still on beta25.1…

but also to me it looks like a bug.

Sorry : 45beta25.0

related / same: https://discourse.vvvv.org/

S+H covers 2 functionalities:

  • S+H the whole spread of the input pin
  • S+H individual slices of the input pin

if the set input isn’t spreaded

  • it samples the whole spread if set=true
  • else it outputs the last sampled spread

if the set input is spreaded this just can be interpreted in a way, that each slice should be S+H individually. in this case S+H behaves as any node that has a slice specific but not spread specific behaviour. think of a damper, where no slice affects the other. In all those cases where nodes only have a slice specific behaviour, we can think of them as a combination of that slice behaviour and an additional spread wrapper.
The slice behaviour is this:

if set[slice mod setcount](slice mod setcount) = true then sample input[slice mod inputcount](slice mod inputcount)

The spread behaviour - in all nodes with only slice specific behaviour - is:

  • output slice count = the maximum slice count of all input spreads
  • repeat the slice specific behaviour for all slices
  • write the outputs

the interesting point is that the S+H with spreaded set pin can only be seen as a normal node, that in each frame calculates the out slice count and after that does its slice specific behaviour (S+H the individual slices).

Still i would be happy if you could report of a use case that would proves me wrong/where you actually need a third different behaviour/where the behaviour described above is buggy.

read the above first.

after thinking again (even harder) i see one inconsistency that is a result of trying to cover 2 functionalities in one node:

let’s focus on the case where a standard spread wrapper is used,
and let’s for now only focus on the slice counts of the 3 pins:

  • i slices in the Input pin

  • s slices in the Set pin

  • we get o slices in the Output pin, where

    o = max(i, s) for (i>0 & s>0) else 0

this behaviour is independant of any values and is recalculated for each frame.
let’s consider the special case s=1.

o = max(i, 1) for (i>0 & 1>0) else 0 = i

the other functionality (S+H the whole spread) however is defined for exactly that case (s=1), and for that case the output slice count o is defined to be dependant of the set value, which shows the inconsistency.

let’s try to give names for both functionalities:

  • the functionality that samples the whole spread: S+H works on a spread and one boolean value: so let’s call that one: S+H(spread of T, bool), where T stands for color, string, number
  • the other case samples each slice individually and doesn’t care about the spread. it just uses the default spread wrapping behaviour… let’s call this one S+H(spread of T, spread of bool) that internally (for each slice) works with a S+H(T, bool)

edit: now we could also imagine a S+H(spread of spread of T, spread of bool) which would internally work with a S+H(spread of T, bool). the slicecount of the output would now be dependant of the spread count(=bin count) within the Input (and the slice count of the Set pin). That means that a NIL on the Input pin wouldn’t necessarily flow through the S+H, since the binsizes could clarify that there are still some spreads inside the Input (all of them being empty themselves); (NIL, NIL, NIL) is something different then NIL…
typically the binsize (or even vector size pins) are needed for advanced spread juggling.
the interesting point here is however, that even the difference between a single value (bool) and a spread of bool can turn into a problem (as shown above). therefore it is just a wonderful example for showing that a spread with one element is something else than just this one element.

(x) != x

note that we devvvvs are well aware of the general problem of implicit spreads in vvvv, but not of all concrete consequences. (we are also aware of the beauty of implicit spreads…)

the mindblowing thing about all that is, that the basic functionality of map(X, bool) can be specified in one sentence: “sample x of any type X, if s=true else return the last sampled x” and should also be a one-liner in code; and what is discussed above is in no way related to the original problem. it is just a discussion over the implicit spread that sits in most pins of vvvv.

so here is how we will solve all the mess:

  • we will keap working on “spread theory” for future generations;) for those begging for even more theory about implicit spreads: vvvv-as-a-language, which is a improved version of my workshop talk at node10…
  • discuss following edited proposal: we should put a BinSize pin into S+H
    ** if BinSize slice count > 1 we have a spread of spread of T in the Input and a spread of bool in the Set pin; repeatedly use functionality of S+H(spread of T, bool).
    ** if BinSize slice count = 1 && Binsize0 >= 0 we have a spread of (T, bool); repeatedly use functionality of S+H(T, bool)
    ** if BinSize slice count = 1 && Binsize0 = -1 we have a (spread of T, bool) only check first bool in the Set pin, ignore the rest; use functionality of S+H(spread of T, bool); do nothing if Set slice count = 0.
    ** NIL for any other BinSize spread
  • implement a new version of S+H, keaping the legacy node to not break patches
    now off for a private road movie.