pure or not pure?

Steven Schveighoffer schveiguy at yahoo.com
Fri Apr 11 12:43:29 PDT 2008


Nope, not close :)  In fact, I want a mutable array because I intend to play 
with the values later in the function (I didn't make that clear I guess).

I agree that in the case that I don't need a mutable array, returning an 
invariant array is an acceptable solution, I don't even think you need a 
class for it, a pure function will do just fine.

But returning a mutable array IMO does not make the function impure, it just 
means you cannot cache the return value.  The compiler could be made to 
assume this when seeing that the return value has a mutable heap pointer.

-Steve

"Koroskin Denis" wrote
On Thu, 10 Apr 2008 17:26:20 +0400, Steven Schveighoffer
 wrote:
> "Janice Caron" wrote
>> On 09/04/2008, Steven Schveighoffer wrote:
>>> So how is new char[] a pure function?
>>
>> new is special.
>>
>>>  And why can't I 'wrap' new?  For
>>>  instance, if I have a function:
>>>
>>>  int[] createIncreasingSequence(int s, int e, int step){...}
>>>
>>>  which creates an array of ints that start at s and end at e, 
>>> increasing
>>> by
>>>  step each time, why can't I make that pure?
>>
>> I reckon you can, but you got the return type wrong.
>>
>>    invariant(int)[] createIncreasingSequence(int s, int e, int 
>> step){...}
>>    {
>>        auto array = new int[(e-s)/step];
>>        foreach(ref a;array)
>>        {
>>            a = e;
>>            e += step;
>>        }
>>        return assumeUnique!(array);
>>    }
>
> This doesn't work for what I'm asking.  I'll add more detail to the 
> example.
> You have two functions f, and g:
>
> pure int f()
> {
>     int[] x = new int[5];
>     for(int i = 0; i < x.length; i++)
>        x[i] = 1 + i;
>
>     /* do stuff */
>     return result;
> }
>
> pure int g()
> {
>     int[] y = new int[15];
>     for(int i = 0; i < y.length; y++)
>         y[i] = 10 + (i * 3);
>
>     /* do stuff */
>     return result;
> }
>
> Now, I realize I have very similar code that initializes the int arrays, 
> so
> I want to put that into a function that creates and initializes an array
> with the given parameters:
>
> int[] createIncreasingSequence(int length, int start, int step)
> {
>     int[] result = new int[length];
>     for(int i = 0; i < result.length; i++)
>         result[i] = start + (i * step);
>     return result;
> }
>
> Now, I think we all agree that createIncreasingSequence is as pure as
> calling new, right?  That is, it doesn't affect any global state (except 
> for
> allocating heap data) and will return an equivalent array every time the
> same arguments are given.  But if I can't declare it as 'pure', then I 
> can't
> call it from f and g:
>
> pure int f()
> {
>    int[] x = createIncreasingSequence(5, 1, 1);
>
>    /* do stuff */
>    return result;
> }
>
> pure int g()
> {
>    int[] y = createIncreasingSequence(15, 10, 3);
>
>    /* do stuff */
>    return result;
> }
>
> So should there be a way to define createIncreasingSequence such that I 
> can
> call it from a pure function?  Or do I have to re-implement it in every 
> pure
> function I use?
>

There is a way with inew (invariant new):

class IncreasingSequence(int length)
{
public:
    this(int start, int step)
    {
       for(int i = 0; i < length; i++)
          elements[i] = start + (i * step);
    }

    int[length] elements;
}

pure int f()
{
    auto x = inew IncreasingSequence!(5)(1, 1);

    /* do stuff */
    return result;
}

pure int g()
{
    auto y = inew IncreasingSequence!(15)(10, 3);

    /* do stuff */
    return result;
}

Isn't it beautiful? Yet, it's /very/ close to wait you wanted. 





More information about the Digitalmars-d mailing list