Problem creating/calling a function

I’m not sure how to ask this question because SC doesn’t seem to act like other languages I’ve worked with(C, C++,Java,Python etc…)

I’m trying to create a function that detects when MIDIcc values change from increasing to decreasing or vice-versa. If there’s something in SC that already does this, please let me know.

Here’s what I have, with comments indicating the errors I’m getting:

MIDIdef.cc(\myVerticleMIDIDef, { |val, num|
	var changes = [1,0];
//	var detectChange = {|val, direction, previousValue| //ERROR: Message 'detectChange' not understood.
	val.detectChange = {|val, direction, previousValue| //ERROR: Message 'detectChange_' not understood.
		if(direction == 1){
			//direction is increasing values
			if(val < previousValue) {[-1,SystemClock.beats];} {[direction,SystemClock.beats];};
		};
		if(direction == -1){
			//direction is decreasing values
			if(val > previousValue) {[1,SystemClock.beats];} {[direction,SystemClock.beats];};
		};
		[direction,SystemClock.beats];
	};

	if(num == ~verticalCC) {
		~verticalBus.set(val/127);
		//changes = detectChange(val, ~verticalDirection, ~previousVerticalValue);//ERROR: Message 'detectChange' not understood.
		changes = val.detectChange(~verticalDirection, ~previousVerticalValue);//ERROR: Message 'detectChange_' not understood.
		~verticalDirection = changes[0];
		~timeInterval = changes[1] - ~previousTimeInterval;
		if(~timeInterval > 0){~myTempoClock.tempo_(60000/~timeInterval/60);}{};
		~previousVerticalValue = val;
		//1.postln;
	};
});

It appears the code is calling detectChange on val as the reciever. But that’s not really my intention. I just want to run the detectChange function with val, ~verticalDirection, ~previousVerticalValue as arguments and store the resulting array in the variable: changes .
What am I doing wrong?

you probably want to define a function detectChange and call it, something like (sorry, untested, but it should give an idea)

(

var detectChange = {
	| val, direction, previousValue |
	if(direction == 1){
		//direction is increasing values
		if(val < previousValue) {[-1,SystemClock.beats];} {[direction,SystemClock.beats];};
	};
	if(direction == -1){
		//direction is decreasing values
		if(val > previousValue) {[1,SystemClock.beats];} {[direction,SystemClock.beats];};
	};
	[direction,SystemClock.beats];
};

MIDIdef.cc(\myVerticleMIDIDef, { |val, num|
	var changes = [1,0];
	if(num == ~verticalCC) {
		~verticalBus.set(val/127);
		// .( is a shortcut for .value(
		changes = detectChange.(val, ~verticalDirection, ~previousVerticalValue);
		~verticalDirection = changes[0];
		~timeInterval = changes[1] - ~previousTimeInterval;
		if(~timeInterval > 0){~myTempoClock.tempo_(60000/~timeInterval/60);}{};
		~previousVerticalValue = val;
	};
});
)

Also consider here that changes is declared within the MIDIdef function. Since it’s local to the function, there’s a new variable changes every time the function gets called, and that variable is discarded when the function exits.

Anything that needs to persist outside of one function invocation must be declared outside of the function (as shiihs did with the detectChange function), or use an environment variable as these are exempt from the local scoping rules of vars.

hjh

Thanks, this worked. detectChange.(val was the key to it.

Thanks for pointing this out. It helped.