On Sunday, 13 December 2015 at 00:36:29 UTC, Namal wrote:
On Sunday, 13 December 2015 at 00:02:11 UTC, cym13 wrote:

Now that I think about it, it's true that it would make no sense whatsoever to return a range as reduce is typically used to return a single value... At least it makes perfect sense.

Thanks alot, this helped alot. But I have another question

I have two functions:
j
int[] prim_factors(int n, const ref int[] P){
        
        int[] v;
        
        for(int i; P[i]*P[i]<=n;++i){
                while(n%P[i]==0){
                        v~=P[i];
                        n/=P[i];
                }
        }
        if(n>1)
                v~=n;
                
        return v.dup.sort.uniq.array;

}


int product(const ref int[] arr){

        int p = 1;
        foreach(i;arr)
                p*=i;
        return p;
}

While vector P contains some primes I get with a prime sieve. So if I just try to use those functions like:

writeln(product(prim_factors(10,P)));

I get the error:

function prog.product (ref const(int[]) arr) is not callable using argument types (int[])

Why do I have to call it like that first:

        auto v = prim_factors(10,P);
        writeln(product(v));

?

That's because you want to modify it in product passing it by ref. In order for it to have a reference (and hence be modified in place) you need it to have some place in memory of which you can take a reference to. This is what rvalues and lvalues are: a rvalue is any value that you'd find on the right side of a "=" like 3. You can't assign a value to 3, it's a rvalue. On the contrary a lvalue is something you'd find on the left side of an "=" like v in your example. You can assign a value to v.

Your problem is that product need a lvalue (as you assign something to it) but you give it a rvalue instead.

The solution is simple: don't ask arr to be passed by reference if you don't intend to modify it.

(I somehow feel like I'm forgetting something there but I can't point it, feel free to destroy)

Reply via email to