Passing arguments to functions Twice?

I am trying to figure out how arguments work still. This is not the full code, just the aspect I’m trying to understand.

Here, you have the function lfo1 with 4 arguments: rate, low, high, and round.
in the “note” variable, for the “in” argument of DegreeToKey, you pass the lfo1 function, and you fill the arguments to lfo1 with:
rate: tempo2
low: 0
high: degreeNum
octRange
round: lfo1.(2,1,7,1) // This is what I’m asking about

I don’t understand what is happening second. First, you have the values being given to lfo1:

lfo1.(tempo*2,0,degreeNum*octRange,lfo1.(2,1,7,1))

And I can understand that, but I can’t seem to wrap my head around what’s happening in the “round” argument. It’s passed the whole of lfo1 again, and given a new set of values for the arguments. So which ones are used? How does the “round” argument take the whole lfo1 function?

var lfo1 = {arg rate,low,high,round; LFNoise0.ar(rate).range(low,high).round(round)};
var	scale = Scale.melodicMinor; 
var	degreeNum = scale.size; 
var note = DegreeToKey.ar(scale.as(LocalBuf),
	    in: lfo1.(tempo*2,0,degreeNum*octRange,lfo1.(2,1,7,1)), // arguments passed to lfo1 twice
		octave:scale.stepsPerOctave,
	    mul: 1,
	    add: octOffset).midicps;

The Function lfo1 is called twice with two different sets of arguments. In object-oriented terms, the Function itself is an object, and each time it’s called, it returns a new object (in this case a BinaryOpUgen, which you can think of as a sort of placeholder for the output of the lfo).

Considered in terms of modular synthesis, you have two of the same lfo with different settings, one of which is patched into one of the “cv inputs” of the other. The Function bound to variable lfo1 is just a recipe for making copies of this particular lfo on demand, and the ability to define these recipes and make these copies is part of what makes SC so powerful.

1 Like

Ok I think it’s starting to make sense.

So correct me if I’m wrong please, but here, lfo1’s “round” argument is getting an actual Signal, an LFNoise0, that is rounding to 1, so that the round argument is dynamically changing, and the end result would look something like this?:

note = DegreeToKey.ar(Scale.melodicMinor.as(LocalBuf),
	in: {arg rate,low,high,rnd; LFNoise0.ar(1).range(0,6).round(
		{arg rate,low,high,rnd; LFNoise0.ar(0.25).range(1,7).round(1)})}
	

If I’m starting to understand correctly, it seems that SC is freaking powerful as HECK…

I’m curious how one knows what Class an argument will take? i.e. is there a method to call what values “round” would take?

I see the method help file, but it doesn’t say much. I see it can take a Signal, probably an Array? Floats and Integers?

Like is there something like: LFNoise0.ar( round: (datatype.postln))? (I know that’s not it, but maybe it makes sense)

Thank you!

Damn, I’m loving this…

Close! What you’re passing as the “in” argument to DegreeToKey.ar is:

LFNoise0.ar(tempo * 2).range(0, degreeNum * octRange).round(LFNoise0.ar(2).range(1, 7).round(1))

So you can see how the arguments that you passed each time the lfo1 function was evaluated were substituted in order to produce the above expression.

I’m curious how one knows what Class an argument will take?

There are certainly people on this board with stronger computer science backgrounds than I have who could probably explain this more elegantly, but the short answer is that the class of an object passed as an argument often doesn’t matter in a strict sense; what matters is whether the object responds to the methods that will be called on it. This idea is called “polymorphism” and is characteristic of many object-oriented languages, including sclang.

To get a sense of how this works in practice, consider that in your example you’ve been able to pass both an Integer and a BinaryOpUgen as the “round” parameter of your Function. The Function doesn’t care what these objects “are”, it cares what they can “do”. To see more examples which will show you how central this idea is to the design of sclang, search the help browser for some common method names such as “play” and have a look at how many different classes implement those methods in different ways.

1 Like

Everything makes sense now…SuperCollider…my life…taxes…Furbies…

Thanks!

1 Like