Performance penalty for using ranges

bearophile bearophileHUGS at lycos.com
Sun Aug 25 13:22:36 PDT 2013


Paul Jurczak:

>> int test(alias F)(in int nLoops) /*pure nothrow*/ {
>>    int[10] a;
>>    typeof(return) n = 0;
>>
>>    foreach (immutable _; 0 .. nLoops) {
>>        a[4] = !a[4];
>>        n += F(a);
>>    }
>>
>>    return n;
>> }
>
> What is the purpose of "immutable _;" above? Why not "i;"?

I have used _ as variable iteration name to remind the person 
that is reading the code that loop variable name is not used 
inside the loop itself. When you have more of those variables you 
can number them as _1, _2, or use no more than two underscores __.

And there the usage of immutable is to disallow the mutation the 
iteration variable inside the loop. In my opinion, to keep code 
clean and less bug-prone D should on make foreach indexes 
immutable on default. This saves you from bugs when you iterate 
on struct items:

struct Foo { int x; }
auto foos = [Foo(10), Foo(20)];
foreach (f; foos)
     f.x++;

It's not uncommon in those cases to forget a "ref" and think foos 
are changed. If iteration items are immutable as in C# this saves 
you from this class of bugs.

I have asked this in past, but D lacks a "mutable" keyword for 
the situations when you want to actually mutate the foreach 
variable, and generally Walter didn't sound very interested on 
this.

So as workaround for this language design problem, it's a good 
habit to always put a const/immutable on foreach variables, 
unless you don't wait it, and unless something forces you to not 
use a const.


>> void main() {
>>    enum size_t nLoops = 60_000_000;
>>    StopWatch sw;
>>
>>    foreach (alg; TypeTuple!(isPalindrome0, isPalindrome1,
>>                             isPalindrome2, isPalindrome3,
>>                             isPalindrome4)) {
>>        sw.reset;
>>        sw.start;
>>        immutable n = test!alg(nLoops);
>>        sw.stop;
>>        writeln(n, " ", sw.peek.msecs);
>>    }
>> }
>
> Same question here: why immutable?

It's explained here:
http://blog.knatten.org/2011/11/11/disempower-every-variable/

In short all your variables/function arguments should be tagged 
as const/immutable unless the semantics of your algorithm needs 
them to mutate, or unless some limit in D/Phobos forbids you to 
(like when you have created a lazy range, currently you can't 
assign it to const and then use it).

Bye,
bearophile


More information about the Digitalmars-d mailing list