(rhetorical) Programming headscratcher. int.loop()

Has anyone ever wondered why this notation is not a common thing?

100.loop();

Or to be more specific:

100.loop(i => Debug.Log(i));

Currently this can be done with an extension method.

static class IntExt{
    public static void loop(this int arg, System.Action<int> callback){
        for(int i = 0; i < arg; i++){
            callback(i);
        }
    }
}

Even though int is a primitive type, it can be extended to have “methods”.

You can also chain those.

int a = ...;
return a.min(b).min(c).min(d).max(e);

Now, you probably shouldn’t do that in production, because the idea is uncommon, and therefore breaches principle of least astonishment, but. I sorta wonder, why this isn’t a common thing somewhere.

Although I did encounter Bjarne Stroutstroup’s proposal to equal methods and functions.

Thoughts?

1 Like

I don’t see this saving me any real time so I’m not inclined to care. I can type “for”, hit Tab twice to auto-complete, and then another time to input the equivalent value. 4-5 is better than ~9, but not by much, and a regular for loop gives you a lot more power if you need it.

The main thing is that most of my loop counts are based off of other variables, or properties of other variables, like the number of agents in my simulation, and while something like activeAgents.Count.loop() could work, it doesn’t seem much quicker or more readable than a traditional for loop.

1 Like

That’s not the part I was thinking of. I was thinking about using method call syntax on integers.

Full version of “for” is way too verbose, by the way, even if you autocomplete it, it’ll require a condition, an incrementer and one extra variable. Meanwhile a single statement loop construct would provide it automatically.

1 Like

I actually added & use a bunch of extension methods like these just for minor convenience sake.
It starts feeling a bit verbose to write this for clamping a minimum value, for instance…

int x = 10;
x = Mathf.Clamp(x, 25, int.MaxValue);

…When I could just use an extension to do this instead:

int x = 10;
x = x.Min(25);

Or approximating floating-point numbers from this…

float x = 0.01f;
float y = 0.0099f;

bool approx = Mathf.Approximately(x, y);

…To this:

float x = 0.01f;
float y = 0.0099f;

bool approx = x.IsApproximately(y);

Or comparing if a number is between two values from this…

float x = 5f;

if(x > 2f && x < 10f) {

}

…To this:

float x = 5f;

if(x.IsBetween(2f, 10f)) {

}

And then it really starts becoming more useful when you involve something like vectors.
Say I want to clamp a minimum value of 1 for a Vector3’s (x,y,z) fields. Well to do that, I’d have to write this normally:

Vector3 vector = new Vector3(-2f, -4f, 12f);

vector = new Vector3(
  Mathf.Clamp(vector.x, 1f, float.MaxValue),
  Mathf.Clamp(vector.y, 1f, float.MaxValue),
  Mathf.Clamp(vector.z, 1f, float.MaxValue)
);

Or write an extension to reduce all of that to just this:

Vector3 vector = new Vector3(-2f, -4f, 12f);

vector = vector.Min(1f);
4 Likes

I don’t think it’s bad at all, I just feel like a for loop is such a fundamental thing that I don’t know that I’d be saving much if any time, and I personally don’t care that much about verbosity in C# (I put my curly braces on their own lines).

Now if we were talking python I’d be on board. Maybe it’s psychological.

I had something similar for Dictionaries. getValueOrDefault, plus bunch of utility functions like getOrCreateComponent(), etc.

I could’ve sworn that unity had an advanced vector operator syntax where | mapped to dot product or something, but apparently I’m wrong and that is actually an Unreal feature.

Once you’ve written for(int i = 0; i < blah; i++) innumerable number of times, having to spell it out again might slowly start driving you nuts, and you might wonder why not loop(10, i => blah(i));

Speaking of verbosity, one of the truly annoying things with C# is that it doesn’t allow free floating functions.
So you can’t just declare float sin(float) it has to be a part of the class, and you’ll need to spell out the name of that class every time you use it. Thankfully extension methods partially alleviate this issue.

Another annoying thing is this construct:

Dictionary<SomeKeyType, SomeValueTypeWithALongName> keyToValueDictionary = new Dictionary<SomeKeyType, SomeValueTypeWithALongName>()

Extra fun when value type is another Generic container.
If you’re in a function you can use var and shorten it.
But if it is a field, as far as I’m aware, you’ll have to type out the whole thing.

1 Like

There is using static though.

With C# 9 you can at least do = new() so you only have to spell out the type once.

2 Likes

Sorry but that’s awesome.

1 Like

This is useful, appreciated.

Unfortunately, unity as of now only supports C#8. Unless I’m missing something.

That’s an interesting idea! Personally I wouldn’t use it as of now, because the compiler currently emits inefficient code for it (or the last time I checked). This syntax creates a “new delegate” under the hood and then calls it, thus it adds pressure on the GC and calls more functions. Nothing I would want to execute per-frame and nothing Unity Technologies and Microsoft recommend to do in game development per-frame.

2 Likes

2021.2 has support for C# 9