Question about examle file drummer synthdef

While analyzing the example file drummer I noticed that both an argument and variable are called the same , tempo
The argument \tempo is a number , and the variable tempo is an Impulse osc.
The speed of the Impulse osc is set by the argument ‘tempo’ , and is then used to control a pulsedivider .
I did something similar , and abviously the use of the same name is giving an error , therefore I renamed the argument \tempo to \Wempo
My question is , in the example file the pulsedivider’s first argument \ tempo , is that the tempo argument or the var temp argument ( the impulse osc ) ?
I assume it’s the impulse osc since there are no conflicts .
The first file is the example ,the second one is my file ’

// (thor magnusson) (2006)

// An instrumentalist inside a synthdef.

(
SynthDef(\drummer, { arg out=0, tempo=4;
	var snare, base, hihat;
	tempo = Impulse.ar(tempo); // for a drunk drummer replace Impulse with Dust !!!

	snare = 	WhiteNoise.ar(Decay2.ar(PulseDivider.ar(tempo, 4, 2), 0.005, 0.5));
	base = 	SinOsc.ar(Line.ar(120,60, 1), 0, Decay2.ar(PulseDivider.ar(tempo, 4, 0), 0.005, 0.5));
	hihat = 	HPF.ar(WhiteNoise.ar(1), 10000) * Decay2.ar(tempo, 0.005, 0.5);

	Out.ar(out,(snare + base + hihat) * 0.4 ! 2)
}).add;
)

a = Synth(\drummer);
a.set(\tempo, 6);
a.set(\tempo, 18);
a.set(\tempo, 180); // check the CPU! no increase.
a.free;```



////my file
(
{
arg modamount=10,wempo=2;
var modenv,ampenv,mod,signal,env,temp,pdv;

temp=Impulse.ar(wempo);
pdv=PulseDivider.ar(temp,1,4);
mod=SinOsc.ar(440/2)*modamount;
modenv=EnvGen.ar(Env([0,1,0],[0.001,0.500],[0,-3]),pdv);
ampenv=EnvGen.ar(Env([0,1,0],[0.001,0.500],[0,-3]),pdv);
signal=SinOsc.ar(220,mod*modenv)*0.3 ;
signal=signal*ampenv;
signal!2;

}.play
)
///

In the initial example there is only an argument called tempo?

In Sc you can mutate function arguments! I.e.

{ arg x; x = 1; x }.value(2) == 1

An identifier can have one and only one declaration within a function’s scope. So there is no “argument and variable… called the same.” tempo must be one or the other. It’s declared as an argument, so that’s what it is.

The only difference between an argument in a variable is that an argument can receive a value from outside the function.

f = { arg x = 1; x * 2 };
g = { var x = 1; x * 2 };

f.value(200);  // 400
g.value(200);  // 2

The arg is initialized from the value inputs. The var is initialized internally, and you can’t change that from outside.

This initial value is the only difference. After that, you can reassign both arguments and variables.

After tempo = Impulse..., then tempo is the Impulse. Its original value is no longer accessible through that name (though it’s been embedded into the Impulse’s inputs).

It’s like this:

a = 1;

// later
a = a + 1;

Now, is a referring to 2, or to 1?

hjh

You’re right , tempo has not been declared as a variable ,just as an argument ,I must have oerseen that .
I know that variables can be re-used and adopt the state of the prevous line of code ( don’t know the exact name for that ) , didn’t know that arguments could do the same thing .
Here’s a piece of code I did , I deleted and replaced all the variable names and used arguments instead and use them in the code ,first only arguments , second only variables
So is there an actual difference when using arguments and or variables , besides that arguments need to be declare=ed first ( given a value ) ?

/////
(
{   arg a=1,b=1,c=1,d=1,n=1,e=1,f=1,wer=1; ////arguments only 
	 

	a = Impulse.ar(8)*1.5;

	b = SinOsc.ar(333,mul:0.5)* Env([1.0,1.0,0.0],[0.01,0.01],-5).ar(0, Impulse.ar(4/2)) ;
	c=EnvGen.kr(Env([0,1,0],[0.001,0.500],[0,-2]),Impulse.kr(4/5))*SinOsc.ar(100,b*MouseX.kr(1,55),mul:0.5);
	d=WhiteNoise.ar(mul:0.25)*EnvGen.ar(Env([0,1,0,1,0],[0,1/1,0,1/2],[0,-5]),Impulse.ar(4/7),doneAction:0);
	n=Resonz.ar(d,2000,0.1);
	wer=LFNoise0.ar(10+(EnvGen.ar(Env([0,1,0],[2,0.5],[50,-5]),Impulse.ar(4/16))*5000))*0.1;
	wer=HPF.ar(wer,1000);
	wer=FreeVerb.ar(b+c+n+wer, 0.4, 0.4)*2.5!2;
}.play
)

/////variables only 
(
{
	var a, b, c, d, n, e, f,wer;

	a = Impulse.ar(8)*1.5;

	b = SinOsc.ar(333,mul:0.5)* Env([1.0,1.0,0.0],[0.01,0.01],-5).ar(0, Impulse.ar(4/2)) ;
	c=EnvGen.kr(Env([0,1,0],[0.001,0.500],[0,-2]),Impulse.kr(4/5))*SinOsc.ar(100,b*MouseX.kr(1,55),mul:0.5);
	d=WhiteNoise.ar(mul:0.25)*EnvGen.ar(Env([0,1,0,1,0],[0,1/1,0,1/2],[0,-5]),Impulse.ar(4/7),doneAction:0);
	n=Resonz.ar(d,2000,0.1);
	wer=LFNoise0.ar(10+(EnvGen.ar(Env([0,1,0],[2,0.5],[50,-5]),Impulse.ar(4/16))*5000))*0.1;
	wer=HPF.ar(wer,1000);
	wer=FreeVerb.ar(b+c+n+wer, 0.4, 0.4)*2.5!2;
}.play
)
/////

The actual difference is that argument defaults can be overridden from outside the function, while vars are completely internal (the function has total control over them).

If it’s purely internal storage, and it’s important that it be initialized your way and not someone else’s way, then it should be a var. (Well, yes, you can do arg x; x = 1 and it will proceed with 1, no matter what the user passed in. But an arg is user-facing – the existence of an arg suggests that it’s meaningful to pass something to it. It’s a bit misleading to publish an arg but then make it meaningless to the caller.)

The other thing to keep in mind is that args are used in a specific way for synthesis functions: they create synth control inputs, and the Control channels are passed in (overriding your defaults).

SynthDef(\test, { arg x = 1;
    x.postln;
});

an OutputProxy  // not 1!

But I think again the concern is the same: a SynthDef’s control inputs may reasonably be expected to have an effect on the sound. If you declare an arg and then replace it completely by something else, then you have a useless control, which is misleading. So you “can” do this but IMO, you shouldn’t. Eventually this sort of untidiness will come back to bite you.

(Note that the drummer example does not discard the control input for tempo.)

hjh