pure-data / pure-data

Pure Data - a free real-time computer music system
Other
1.56k stars 244 forks source link

`[change]`: initialize with null #2173

Open brianlindgren opened 8 months ago

brianlindgren commented 8 months ago

It seems that the change object's initial value is zero. This causes issues if I'd like change to pass a zero if that's the first number it receives.

It would be great if the initial value was null. Thoughts?

ben-wes commented 8 months ago

did you check the help for the object? an actual null is currently not possible. but you can initialize it with any non-zero value if you want it to trigger with the first 0.

e.g., you can init with change -1 or change 1e+09 ... whatever is outside the expected range of incoming values (you can also set the current value to detect changes from via a set-message).

brianlindgren commented 8 months ago

thanks for the quick reply. Yes I checked the help. This was more of a feature request; if null would be possible that would be ideal. But yes, I'm using the method you mentioned. thanks again

umlaeute commented 8 months ago

while i like the idea, i wonder whether this would break patches that rely on the implicit [change 0] behaviour.

Ant1r commented 8 months ago

we could add a [change null], i.e if the argument is a symbol then any number would trigger the change?

umlaeute commented 8 months ago

hmm, really?

i would expect a [change foo] object to go into symbolic mode (just like [route foo] and [select foo]).

also the literal null has no special meaning within Pd, this seems to be not a good place to introduce it. (if any, bang would be more appropriate)

Ant1r commented 8 months ago

the best would be to allow mixing numeric and symbolic mode, which would obviously allow any number to trigger the change. So we could even [set foo(, as well as we can [set 0(.

ben-wes commented 8 months ago

also the literal null has no special meaning within Pd, this seems to be not a good place to introduce it. (if any, bang would be more appropriate)

would empty be a valid literal in that case as well (since it exists elsewhere already iirc)? i'm not so sure about that option neither though since it seems weird to actually state emptiness where it could just stay empty.

porres commented 8 months ago

seems to make more sense to just use a flag, '-null' or whatever else

Lucarda commented 8 months ago

though since it seems weird to actually state emptiness where it could just stay empty

as stated by @umlaeute above, "no args" behavior must not change as (pre)existing patches may rely on "that" behavior.

ben-wes commented 8 months ago

"no args" behavior must not change as (pre)existing patches may rely on "that" behavior.

sure. didn't want to question that - sorry if that wasn't clear (i'm pretty sure that my own patches' behavior would change in some cases). i just meant that an explicit empty wouldn't seem too intuitive (for someone that's not aware of the background story here).

umlaeute commented 8 months ago

the best would be to allow mixing numeric and symbolic mode,

we could, but I think we should allow mixing the two modes in [select] and [route] first

would empty be a valid literal (since it exists elsewhere already iirc)

it's used by the iemguis to mean "no label" (or send/receive), but that's an implementation detail not exposed to the user (there's only two ways to be aware of it: read patch files/source code in your favourite text viewer)

in any case, it is broken by design. let's not repeat such folly. (the only other way to discover the special meaning of empty in iemguis is by hitting the bug that you cannot use empty as a label)

seems to make more sense to just use a flag, -null

this is just a random word without any meaning within Pd (much like the original null).

or whatever else

so far, i think exactly null suggestions make much sense (to me).

probably the best so far has been 1e+09 (if you prefer a flag-like argument, use -1e+9): it's equally arbitrary as none, -none and empty, but has the benefit of already working out of the box (unless you are very unlucky).


as stated by @umlaeute above, "no args" behavior must not change

i did not say that it must not change. i said (well: meant) that we need to be aware of the implications of such a change.

on revisiting the (history of) the [change] help-patch, I see that the documentation is very silent about the behaviour of the object when instantiated without an argument. so we could argue in favour of the OP and distinguish between [change] and [change 0]. and probably hide this incompatibility behind one of those abominable pd compatibility flags.

umlaeute commented 5 months ago

here's another idea that would be backwards compatible: allow the use of the literal NaN to initialize the start value of [change] to a known invalid number.

in general i would like to be able to use NaN, inf and -inf for numbers, probably restricted to:

ben-wes commented 5 months ago

sounds quite intuitive to me.

so this would also allow checks like [== NaN]? ... and in the future possibly for signals with [==~ NaN]?

Spacechild1 commented 5 months ago

here's another idea that would be backwards compatible: allow the use of the literal NaN to initialize the start value of [change] to a known invalid number.

SuperCollider uses non-signalling NaNs when it needs to initialize members to some invalid value so that every subsequent comparison will yield false.

Note that this only works if the code is compiled without -ffinite-math-only (which is implied with -ffast-math). Otherwise it can fail in subtle ways: https://stackoverflow.com/questions/57894032/floating-point-comparison-with-quiet-nan-on-gcc-with-ffast-math-always-yields

Traditionally, Pd has always been compiled with -ffast-math, but lately the autotools build system has been quietly changed to -ffast-math -fno-finite-math-only (https://github.com/pure-data/pure-data/commit/ed82e981a826fad848eb913b0571998aaaf3b53c). Note that the old makefiles (src/makefile.gnu, src/makefile.mac) and the libpd makefile (libpd/Makefile) still use -ffast-math (implying -ffinite-math-only)!

I really have some concerns with adding logic to Pd that depends on floating point optimizations because this might open a can of worms. Of course, we can update our build systems to include -fno-finite-math-only, but the Pd sources are also used by a few external projects. Traditionally, everyone could just compile the Pd sources with any optimization flags they like and it would just work; these days would be gone. I'm also afraid that external authors would pick up this pattern because pd-lib-builder also uses -ffast-math by default.

Spacechild1 commented 5 months ago

It's also worth noting that some compilers don't offer floating point optimizations with the necessary granularity. For example, the MSVC equivalent to -ffast-math would be /fp:fast, but AFAICT there is no way to specifically exclude NaNs: https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior?view=msvc-170. If Pd relied on NaNs, MSVC builds could not use any floating point math optimizations beyond /fp:contract.

umlaeute commented 5 months ago

so this would also allow checks like [== NaN]?

depends on what you want. but, by definition NaN != NaN, so your [== NaN] will always yield false.