pure or not pure?

Koroskin Denis 2korden+dmd at gmail.com
Fri Apr 11 12:21:48 PDT 2008


On Thu, 10 Apr 2008 17:26:20 +0400, Steven Schveighoffer  
<schveiguy at yahoo.com> 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