Exactly. I vividly remember our (Bartosz, Walter, me) discussion that settled this - the competing approach was to define distinct syntactic constructs for "head const", "tail const", and "all const".

Back then we decided that three flavors of const (and three of immutable) would be unacceptable as too complex. We decided that tail const for arrays was already possible syntactically (const(T[]) vs. const(T)[]) and that we'll leave libraries to define their own const(Artifact!T) vs. Artifact!(const T) if they so need.

I think it's okay to change the compiler to automatically convert const(T[]) to const(T)[] upon any function call. The function's parameter is private anyway. There's hardly any loss of information - I doubt a function could actually be interested in that distinction.


Andrei

David Simcha wrote:
Ok, now I get why using Unqual to get tail const wouldn't work. My silly oversight:

// The following doesn't work, though the natural tail
// const for const(Cycle!(int[])) is Cycle!(const(int)[]),
// because Unqual!(const(Cycle!(int[]))) == Cycle!(int[]).
import std.range, std.traits;

void main() {
    const myRange = cycle([1,2,3,4]);
    pragma(msg, typeof(myRange));

    Unqual!(typeof(myRange)) myRangeMutable = myRange;
    pragma(msg, typeof(myRange));
}


On Thu, Aug 12, 2010 at 11:37 AM, Steve Schveighoffer <[email protected] <mailto:[email protected]>> wrote:

    Tail-const is doable, but does not enjoy the implicit conversion
    that T[] has.

    Without the implicit conversion, tail-const relies on unsafe
    casting, and that
    sucks.

    I agree with Andrei we need a language solution.  The question
    really is not
    what the solution should do, that much is clear -- apply const to a
    subset of
    the members (either all references or members designated by some
    identifier).
    The question is, what does the syntax look like.  That was the major
    stumbling
    block that flipped Walter's switch to "tail-const doesn't work".

    I think we should concentrate on structs and not class references,
    since class
    references have no syntax that separates the reference from the
    data.  At least
    with structs, you can identify the parts to apply const to.  We have
    a somewhat
    clunky solution in Rebindable for classes, so it would be nice to
    include them,
    but past experience has shown that to be a big rat hole.

    -Steve

     >
     >From: David Simcha <[email protected] <mailto:[email protected]>>
     >To: Discuss the phobos library for D <[email protected]
    <mailto:[email protected]>>
     >Sent: Thu, August 12, 2010 11:28:24 AM
     >Subject: Re: [phobos] is*Range + Qualified Types
     >
     >
     >
     >
     >On Thu, Aug 12, 2010 at 1:43 AM, Andrei Alexandrescu
    <[email protected] <mailto:[email protected]>> wrote:
     >
     >
     >>
    I think the main argument is that currently most of std.algorithm
    doesn't work
    with const arrays, which have a simple "tail-const" version.
    const(T[]) is
    implicitly convertible to const(T)[].
     >>
     >>That doesn't apply to most other ranges, which don't have an obvious
     >>"tail-const" version.
     >>
     >>David, I think we need to think through a bit more before
    proceeding. The way I
     >
     >>assume you want to proceed is to essentially add a special
    function signature
     >>for each algorithm and have it forward to the peeled version.
    Perhaps we could

     >>look at a simpler solution, e.g. one that would involve a
    language change.
     >>

    Fair enough.  If you think this might be better solved at the
    language level,
    that's a worthwhile discussion to have.  I do believe, though, that
    most ranges
    besides T[] do have an obvious "tail-const" version, since in
    practice most
    ranges are structs that have the iteration state stored inline and
    only use
    indirection to store the payload, if anywhere.

    At any rate, I think this is a must-solve problem.  Despite its
    theoretical
    beauty, I find D's const/immutable system to be utterly useless (and
    I've made a

    serious attempt to use it in a real multithreaded program) for all
    but the
    simplest cases in practice, for three reasons:

    1.   It's too hard to create non-trivial immutable data structures,
    especially
    without relying on unchecked casts during construction.

    2.  So many things in Phobos (even things as simple as
    std.math.pow() before I
    recently fixed it) behave incorrectly when given const/immutable
    data.  This
    also applies to other libraries I use, including ones that I'm the
    main author
    of, so I'm just as guilty of it as anyone.  Given that noone,
    including me,
    seems to be able to get this right in generic code, perhaps this
    does point to
    the need for a language-level solution.

    3.  inout is currently so bug-ridden it's not even funny.



    _______________________________________________
    phobos mailing list
    [email protected] <mailto:[email protected]>
    http://lists.puremagic.com/mailman/listinfo/phobos



------------------------------------------------------------------------

_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos
_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos

Reply via email to