# Explanation for how the server handles if()?

Hi all,

I don’t really have a problem here, just trying to understand some unexpected behaviour.

``````(
{
var sevens = DC.kr(7);
Poll.kr(Impulse.kr(60), [

sevens,

if(sevens == 7, 1, 0),
if(sevens < 7, 1, 0),
if(sevens > 7, 1, 0),

if(7.0 == 7, 1, 0),
if(sevens <= 7, 1, 0),
if(sevens >= 7, 1, 0),

])
}.play
)
``````

The above code polls 7 lines, which all seem to contradict each other a bit; `DC.kr(7)` is not equal to 7, nor is it less than or greater than 7.

Insight into what’s happening on a low level would be appreciated.

The ‘==’ operator is somehow exceptional. If you look at the implementations of ‘<’, ‘>’, ‘<=’ and ‘>=’, you see that these operators (methods) are defined for UGens via the superclass AbstractFunction. For some reason this is not the case for ‘==’, so the operator’s implementation for AbstractFunction’s superclass Object is applied and you end up with a result, which is no UGen, which breaks the ‘if’ pseudo ugen:

``````    if { arg trueUGen, falseUGen;
^(this * (trueUGen - falseUGen)) + falseUGen;
}
``````

If you want to make such work, you can e.g. use the (not very handsome) syntax

``````(
{
var sevens = DC.kr(7);
Poll.kr(Impulse.kr(1), [

sevens,

if(BinaryOpUGen('==', sevens, 7), 1, 0),
if(sevens < 7, 1, 0),
if(sevens > 7, 1, 0),

if(sevens <= 7, 1, 0),
if(sevens >= 7, 1, 0),

])
}.play
)
``````

By the way the analogue problem occurs with Pif and ‘==’, you can’t use this, instead replace with Pbinop(’==’ etc. This is fooling people since … decades, I feel There doesn’t seem to be an easy workaround though.

``````(
SynthDef(\help_sinegrain,
{ arg out=0, freq=440, sustain=0.05;
var env;
env = EnvGen.kr(Env.perc(0.01, sustain, 0.2), doneAction: Done.freeSelf);
Out.ar(out, SinOsc.ar(freq, 0, env))
)

(
var a;
a = Pif(
Pfunc({ [0, 1].choose } == 0),   // doesn't work
// Pfunc({ [0, 1].choose } < 1),   // works
// Pbinop('==', Pfunc({ [0, 1].choose }), 0), // works
Pn(Pseries(0.5, 0.1, 10)), Pn(Pseries(6, -0.1, 10))
).asStream;
{
loop {
Synth(\help_sinegrain, [\freq, a.next * 600 + 300]);
0.2.wait;
}
}.fork;
)
``````

And actually the original example of this help file is not ideal IMO, as it implements a syntax which leads to inexact timing, but this is another story:

http://doc.sccode.org/Guides/ServerTiming.html

1 Like

… ah, I’ve made a mistake in showing the disfunctionality, but this doesn’t change anything:

`Pfunc({ [0, 1].choose } == 0),`

you would want to write

`Pfunc({ [0, 1].choose }) == 0,`

but it doesn’t function either

Brilliant, that makes perfect sense. Thank you! I guess this is the kind of reason why === is part of JavaScript?

The BinaryOpUGen function could be useful in the future (​:

Another interesting detail: you can apply operators to Functions

``````{ [0, 1].choose } < 1

-> a BinaryOpFunction
``````

as a consequence it doesn’t matter in that case if we write the operator inside or outside Pfunc’s argument !

Equivalent:

``````Pfunc({ [0, 1].choose } < 1).asStream.nextN(100)

(Pfunc({ [0, 1].choose }) < 1).asStream.nextN(100)
``````

But, here too, ‘==’ isn’t defined for Function – as it isn’t for AbstractFunction – so both ‘==’ variants don’t work.