Skip current iteration in forloop (like 'continue' keyword in other languages)?

hello there,
this might be a simple question but i can’t seem to find anything in the documentation.
is there a way to skip an iteration while iterating over a collection within sclang?

I have an array of objects I want to iterate over but only do something with if a certain attribute of the object is what i want. I’m used to doing this in other languages as a sort of early return to avoid a bunch of nesting for cleaner code.
i.e.

stuff.do {
    | thing |
    if (thing.shouldBeSkipped, {
        continue
    });
    ...
}

Is there a similar ‘continue’ keyword in sclang, or is filltering beforehand with something like Array.select() the only option?
thanks

1 Like

Maybe I’m missing something, but it could be as simple as:

stuff.do {
| thing |
if (thing.shouldBeSkipped.not, {
    do_something(thing);
};
};

There are some other related methods like

(
[1, 2, 3, 4].select({ arg item, i; item.even }); // [2,4]
[1, 2, 3, 4].reject({ arg item, i; item.even }); // [1,3]
)

Ah yes thanks, that is how i’ve been doing it at the moment.
My example was pretty basic for levity, usually I have several checks with some lookups that should only happen if the first check passed etc, it would simply look cleaner if I could just skip it right away, and it would mean no need for repeating the code in the case it should execute.
It’s really not that big of a deal though I’m just a bit nitpicky about the style i’m used to sometimes.
I’ll probably just go for for the Array.select strategy.
cheers

Certainly ok, but thinking about it … in some cases it might be unnecessary to make a new array (which is what select does). E.g., if this operation is repeated quite often, it might be very wasteful.
There are many hardly known and hardly seen methods, spread over the classes Array, Collection, SequenceableCollection, List etc. Often there exists one which does exactly what you expect. Many of them do something with Functions, e.g., selectIndices. A “restricted do” looks totally reasonable to me and I’m asking myself why something doesn’t yet exist (if I haven’t overlooked such, there are other much more exotic operations implemented).

Anyway, it’s easy to add something as .sc file in your Extensions folder

+ SequenceableCollection {
	ifDo { |ifFunc, func|
		this.do { |item, i|
			ifFunc.(item, i).if { func.(item, i) }
		}
	}
}

Then after recompile

(1..10).ifDo({ |x| x % 3 == 0 }, { |x| (x * x).postln }) 

// the parser also accepts this

(1..10).ifDo { |x| x % 3 == 0 } { |x| (x * x).postln }
1 Like

I don’t see the necessity of a continue keyword. If the continue is conditional, then the same meaning can be expressed by if (though potentially continue could flatten some nesting, it doesn’t really add functionality); if it isn’t conditional, then it would render the code after it redundant (so, no point).

There’s probably a clean way to express it in SC without continue, even in the more complex case… maybe give a more specific example and a bunch of us could think of efficient ways to write it.

hjh