September 22, 2011
Jesse Phillips wrote:

> The discussion on Reddit brought to my attention that pure functions can return and assign to an immutable.
> 
> 
http://www.reddit.com/r/programming/comments/knn5p/thoughts_on_immutability_in_d/c2lsgek
> 
> I am trying to modify the example request to make use of this, but have failed.
> 
> 
http://www.reddit.com/r/programming/comments/knn5p/thoughts_on_immutability_in_d/c2lrfpm
> 
> test.d(4): Error: cannot implicitly convert expression
> (makeFromArray([1,2,3])) of type test.List!(int).List to immutable(List)
> 
> Is this a bug? I can't identify where this issue would lie (works with
> inheritance and templating).
> 
> void main() {
>    immutable a = makeFromArray([1,2,3]);
> }

For this to work, the arguments to makeFromArray have to be immutable:

void main() {
    immutable(int)[] data = [1,2,3];
    immutable a = makeFromArray(data);
}

> private abstract class List(T) {
>    abstract bool isEmpty () const;
>    abstract T head () const;
>    abstract const(List!T) tail () const;
> 
> 
> }
> private final class Cons(T): List!T {
>    immutable T head_;
>    Cons!T tail_; // not immutable here for a reason
> 
>    this(T h, Cons!T t) { head_ = h; tail_ = t; }
> 
>    override bool isEmpty() const { return false; }
>    override T head () const { return head_; }
>    override const(Cons!T) tail () const { return tail_; }
> }
> 
> List!T makeFromArray(T)(T[] array) pure {

makeFromArray must take and return immutable types:

immutable(Cons!T) makeFromArray(T)(immutable(T[]) array) pure

>    if (array.length == 0) { return null; }
> 
>    auto result = new Cons!T(array[0], null);
>    auto end = result;
> 
>    for (int i = 1; i < array.length; ++i) {
>       end.tail_ = new Cons!T(array[i], null);
>       end = end.tail_;
>    }
> 
>    return result;
> }

September 22, 2011
On Thu, 22 Sep 2011 17:03:08 -0400, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

>
> In any case, in order for a function to be able to have its return value
> implicitly value implicitly cast to immutable, it must pure and all of its
> arguments must be immutable or implicitly convertible to immutable (or - if
> the compiler is ever improved to treat pure functions with const parameters
> and immutable arguments the same way - the requirement would be that the
> function must be pure and all of its _arguments_ must be immutable or
> implicitly convertible to immutable).

No, the parameter types can be const, and can accept mutable arguments.  The main point is, the return value has to be proven to be *unique*.  The only way to do this with pure functions is to prove that the result is *not* a subset of the parameters.  That's all.

Observe:

char[] foo(const(char)[] x) pure {...}

There is no way to write the body of this function such that the return value is a substring of x.  So you are guaranteed that the result is *new memory*, and since it cannot be stored globally anywhere (per pure rules), it's guaranteed to be unique, and should be implicitly castable to immutable.

Even if you pass a char[] into foo.

-Steve
September 22, 2011
On Thursday, September 22, 2011 14:03 Jonathan M Davis wrote:
> In any case, in order for a function to be able to have its return value implicitly value implicitly cast to immutable, it must pure and all of its arguments must be immutable[...]

Ouch! I really must reread my posts more before posting. That's understandable but pretty bad. :(

I guess that I'm frequently in too much of a hurry when posting.

- Jonathan M Davis
September 22, 2011
On Thursday, September 22, 2011 14:10 Steven Schveighoffer wrote:
> On Thu, 22 Sep 2011 17:03:08 -0400, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > In any case, in order for a function to be able to have its return value
> > implicitly value implicitly cast to immutable, it must pure and all of
> > its
> > arguments must be immutable or implicitly convertible to immutable (or -
> > if
> > the compiler is ever improved to treat pure functions with const
> > parameters
> > and immutable arguments the same way - the requirement would be that the
> > function must be pure and all of its _arguments_ must be immutable or
> > implicitly convertible to immutable).
> 
> No, the parameter types can be const, and can accept mutable arguments. The main point is, the return value has to be proven to be *unique*. The only way to do this with pure functions is to prove that the result is *not* a subset of the parameters. That's all.
> 
> Observe:
> 
> char[] foo(const(char)[] x) pure {...}
> 
> There is no way to write the body of this function such that the return value is a substring of x. So you are guaranteed that the result is *new memory*, and since it cannot be stored globally anywhere (per pure rules), it's guaranteed to be unique, and should be implicitly castable to immutable.
> 
> Even if you pass a char[] into foo.

Hmmmm. You're right. Bleh. This is overly complicated. It works, but sorting it out is a pain. And trying to explain to newbies why and when a function can have its return value implicitly converted to immutable... Well, it's going to be an issue - just like with strong purity, but in that case at least, we can pretty much just let the compiler optimize where it's going to optimize and not generally worry about what's strong or weakly pure unless you're really trying to optimize code. In this case, however, programmers are going to need to understand in order to use it properly.

- Jonathan M Davis
September 22, 2011
Dmitry Olshansky Wrote:


> Maybe:
> -------------------------<<<<<<<<<<
>   List!T makeFromArray(T)(immutable T[] array) pure {
> -- 
> Dmitry Olshansky

Thank you this lets it compile. I think I had that somewhere, but forgot about it. As Steve mentions, it probably should also work for const arguments too.
September 22, 2011
Jesse Phillips:

> Thank you this lets it compile. I think I had that somewhere, but forgot about it. As Steve mentions, it probably should also work for const arguments too.

If you are convinced of this, then I suggest you to add an enhancement request in Phobos about it. It will make purity more and more useful.

Bye,
bearophile
September 23, 2011
"Jesse Phillips" <jessekphillips+D@gmail.com> wrote in message news:j5gfsa$2d5g$1@digitalmars.com...
> Thank you this lets it compile. I think I had that somewhere, but forgot about it. As Steve mentions, it probably should also work for const arguments too.

It probably will, eventually.  Some expressions can be proven to be pure (in some situations), such as (new C), (arr ~ arr), (arr.dup) and (thisFunctionIsConstPure(args))

(doing this for arr ~ arr is the best solution to http://d.puremagic.com/issues/show_bug.cgi?id=1654, in my opinion)

As Steven pointed out, pure functions that have mutable return types cannot be opimized out, as the code could reasonably rely on returned objects being distinct.  Their return values can, however, be converted to immutable without any problems.


September 23, 2011
On Thu, 22 Sep 2011 22:18:29 +0100, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> On Thursday, September 22, 2011 14:10 Steven Schveighoffer wrote:
>> No, the parameter types can be const, and can accept mutable arguments.
>> The main point is, the return value has to be proven to be *unique*. The
>> only way to do this with pure functions is to prove that the result is
>> *not* a subset of the parameters. That's all.
>>
>> Observe:
>>
>> char[] foo(const(char)[] x) pure {...}
>>
>> There is no way to write the body of this function such that the return
>> value is a substring of x. So you are guaranteed that the result is *new
>> memory*, and since it cannot be stored globally anywhere (per pure rules),
>> it's guaranteed to be unique, and should be implicitly castable to
>> immutable.
>>
>> Even if you pass a char[] into foo.
>
> Hmmmm. You're right. Bleh. This is overly complicated. It works, but sorting
> it out is a pain. And trying to explain to newbies why and when a function can
> have its return value implicitly converted to immutable... Well, it's going to
> be an issue - just like with strong purity, but in that case at least, we can
> pretty much just let the compiler optimize where it's going to optimize and
> not generally worry about what's strong or weakly pure unless you're really
> trying to optimize code. In this case, however, programmers are going to need
> to understand in order to use it properly.

The key word here is "unique".  It "makes sense" that "unique" data can be implicitly cast to immutable, because it only exists once, in one place, and no-one/thing else knows about it.. therefore it can be considered immutable.

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
1 2
Next ›   Last »