February 17, 2012
On 2/16/12 6:49 PM, SiegeLord wrote:
> On Thursday, 16 February 2012 at 23:14:54 UTC, Andrei Alexandrescu wrote:
>> Hold them horses. I disagree. You're just saying it, but what's your
>> basis?
>
> Because some cases (as shown below) trivially work within the const
> system, while some closely related ones don't. You're not going to be
> able to convince me of a demarcation that requires some const issues to
> require templates, and some not.

Some cases also work trivially with subtyping, while some closely related ones don't.

>> This boils down to: "You want to sort an array of T[], U[], or V[],
>> where the three types are loosely-related, except U is a supertype of
>> both T and V and the three have the same layout. What would be the
>> signature of such a function?"
>>
>> The answer is (to a reasonable approximation) simple:
>>
>> sort(X)(X[] data) if (is(X : U) && X.sizeof == U.sizeof);
>>
>> This has nothing to do with qualifiers.
>
> Because you removed them. While I agree with the type argument to a
> point, qualifiers have more meaning than just arbitrary type creation:
> they talk about mutability.

That's a given. But that doesn't confer them infinite powers otherwise inaccessible; you seem to require any flexibility that seems reasonable within a context, and that's simply put impossible. There is a point where inout's powers stop (inout can be considered a special case designed for a few common cases).

I should confess that the subtyping relation (const(T) is a supertype of both T and immutable(T)) has from day 1 been a guiding design principle for us, so that shouldn't be taken lightly. There is a relation between types that is somewhere in between simple subtyping and qualified types: subtype with layout conservation, i.e. you know that T is a supertype of U and both T and U have identical layout. For such types we could accommodate special capabilities in the type system; they'd be applicable beyond qualified types.

> The desired function signature states that
> the contents of the strings that are in the array will not be modified,
> your generic version does not have that stipulation.
> I can make up a
> body for that sort function which will work for types which fit your
> description, but fail for const(char)[], char[] and immutable(char)[].

I think it's well worth trying this exercise. Given

class Base {}
class D1 : Base {}
class D2 : Base {}

define a non-template function that sorts Base[], D1[] and D2[] without casts.

>> I don't know how to swim with a hand tied to my back, either. The
>> correct approach is to integrate templates in the discussion and
>> analyze _that_ context, not the artificial context that precludes
>> templates. D is not Go.
>
> As much as you might prefer D to be 100% about templates,

(let's stay on topic and not make this ad hominem, thanks)

> it is not, and
> there is a subset of it which is usable without them.

This calls for the obvious answer that there's a subset of D that's usable without const.

> This subset is the
> subject of this thread. There is no a priori reason why the first case
> should work and second should not within the confines of the const system.

I understand your complaint, but I don't know how to design a type system that is at the same time reasonably small and simple and allows all of your examples and some related ones. We have "inout" which is helpful but at the end of the day a special case for a category of situations. We can't expect it to do miracles.


Andrei
February 17, 2012
On Friday, 17 February 2012 at 02:39:29 UTC, Andrei Alexandrescu wrote:
> That's a given. But that doesn't confer them infinite powers otherwise inaccessible; you seem to require any flexibility that seems reasonable within a context, and that's simply put impossible. There is a point where inout's powers stop (inout can be considered a special case designed for a few common cases).

And can this not be a special case with a new type too? The issue is of moving the elements in an array while retaining the const correctness on the contents of the elements. Something like a rebindable reference to a constant memory?

> I think it's well worth trying this exercise. Given
>
> class Base {}
> class D1 : Base {}
> class D2 : Base {}
>
> define a non-template function that sorts Base[], D1[] and D2[] without casts.

Naturally you can't, but that wasn't my point. My point was that I could do this:

sort(X)(X[] data) if (is(X : const(char)[]) && X.sizeof == (const(char)[]).sizeof)
{
     data[0][0] = 1;
}

This would compile just fine if you passed it a char[][]. Your templated function doesn't describe the semantics of the function (it shouldn't change the elements of the array, just their order). Is there a way around it? Is it better than casting?

> This calls for the obvious answer that there's a subset of D that's usable without const.

Yes, but it doesn't have these bizzarities.

I like having const correctness in my code, I like the assurance that my memory isn't being mutated. Once I start using templates, it seems that that assurance can go out of the window sometimes because the template system is defined on the level of types, not on the level of const qualifiers.

-SiegeLord
February 17, 2012
On Friday, February 17, 2012 06:54:44 SiegeLord wrote:
> On Friday, 17 February 2012 at 02:39:29 UTC, Andrei Alexandrescu
> 
> wrote:
> > That's a given. But that doesn't confer them infinite powers otherwise inaccessible; you seem to require any flexibility that seems reasonable within a context, and that's simply put impossible. There is a point where inout's powers stop (inout can be considered a special case designed for a few common cases).
> 
> And can this not be a special case with a new type too? The issue is of moving the elements in an array while retaining the const correctness on the contents of the elements. Something like a rebindable reference to a constant memory?

If the elements are really const, then you can't move them. Period. Doing so would violate const. Now, you can have references or pointers to const and move _those_ around, but then the elements themselves aren't really const. If you're dealing with objects, you can use std.typecons.Rebindable, though there is a pull request (which has been around a while and may never get merged in) which adds syntax for references to const, in which case Rebindable wouldn't be needed anymore.

> > This calls for the obvious answer that there's a subset of D that's usable without const.
> 
> Yes, but it doesn't have these bizzarities.
> 
> I like having const correctness in my code, I like the assurance that my memory isn't being mutated. Once I start using templates, it seems that that assurance can go out of the window sometimes because the template system is defined on the level of types, not on the level of const qualifiers.

Templates can't violate const anymore than other code can. Templates don't strip constness. If you're passing const variables to a templated function, they're const in the templated function. And if the templated function wants to guarantee that what you pass in doesn't get altered, then it can mark its parameters const just like any other function can. Templates do nothing to screw up const.

- Jonathan M Davis
February 17, 2012
"Jonathan M Davis" <jmdavisProg@gmx.com> wrote in message news:mailman.457.1329458451.20196.digitalmars-d@puremagic.com...
> there is a pull request (which has been around a while and may never get merged in)

It or something like it will most likely get merged in eventually.


February 17, 2012
On 02/17/2012 06:54 AM, SiegeLord wrote:
> On Friday, 17 February 2012 at 02:39:29 UTC, Andrei Alexandrescu wrote:
>> That's a given. But that doesn't confer them infinite powers otherwise
>> inaccessible; you seem to require any flexibility that seems
>> reasonable within a context, and that's simply put impossible. There
>> is a point where inout's powers stop (inout can be considered a
>> special case designed for a few common cases).
>
> And can this not be a special case with a new type too? The issue is of
> moving the elements in an array while retaining the const correctness on
> the contents of the elements. Something like a rebindable reference to a
> constant memory?
>
>> I think it's well worth trying this exercise. Given
>>
>> class Base {}
>> class D1 : Base {}
>> class D2 : Base {}
>>
>> define a non-template function that sorts Base[], D1[] and D2[]
>> without casts.
>
> Naturally you can't, but that wasn't my point. My point was that I could
> do this:
>
> sort(X)(X[] data) if (is(X : const(char)[]) && X.sizeof ==
> (const(char)[]).sizeof)
> {
> data[0][0] = 1;
> }
>
> This would compile just fine if you passed it a char[][]. Your templated
> function doesn't describe the semantics of the function (it shouldn't
> change the elements of the array, just their order). Is there a way
> around it? Is it better than casting?
>

As I suggested in my other post, use inout(void) sort(inout(char)[][]) for the semantics you want.

>> This calls for the obvious answer that there's a subset of D that's
>> usable without const.
>
> Yes, but it doesn't have these bizzarities.
>
> I like having const correctness in my code, I like the assurance that my
> memory isn't being mutated. Once I start using templates, it seems that
> that assurance can go out of the window sometimes because the template
> system is defined on the level of types, not on the level of const
> qualifiers.
>
> -SiegeLord

Template functions cannot violate const correctness any more than normal functions can.



February 17, 2012
On Thu, 16 Feb 2012 16:48:27 -0500, SiegeLord <none@none.com> wrote:

> Firstly, let me preface this... if you use templates to get around the const system's imperfections, you are admitting that the const system is broken. Now, on with the program.
>
> My unique experience in using D2 without Phobos lead me to encounter two cases that show how the D2 const system is just a pain in the behind for some really reasonable tasks.

inout should solve all these problems.  As Timon says, there are bugs with it.  Bugs do not mean the design is not sound.

Also note that you are not unique in that experience, I tried to port Tango to D2 a long time ago, and the bug report 1961 was a direct result of trying that porting.  In other words, inout was *designed* to allow Tango to be ported to D2.

-Steve
1 2
Next ›   Last »