Writing const-correct code in D

Johan Granberg lijat.meREM at OVEgmail.com
Wed Mar 8 06:35:49 PST 2006


xs0 wrote:
> Kevin Bealer wrote:
>> Also, this is not full "C++ const", only parameter passing and const
>> methods, which seems to be the most popular parts of the const idea.
>> It seems like it should require more syntax that C++, but it only
>> takes a small amount.
>>
>>
>> When working with types like "int", use "in" - const is not too much
>> of an issue here.
>>
>> The same is true for struct, it gets copied in, which is fine for
>> small structs.  For larger structs, you might want to pass by "in *",
>> i.e. use "in Foo *".  You can modify this technique to use struct, for
>> that see the last item in the numbered list at the end.
>>
>>
>> For classes, the issue is that the pointer will not be modified with
>> the "in" convention, but the values in the class may be.
>>
>>  // "Problem" code
> 
> OK, this is like the 5000th post I've read regarding const correctness 
> and related issues in D. Can we really not come to some kind of an 
> agreement on what would be best? I'm sure if there's a consensus about a 
> solution, Walter will eventually implement it.
> 
> I've read the paper Andrew posted a link to in the last const thread, 
> and I really like that system:
> http://pag.csail.mit.edu/pubs/ref-immutability-oopsla2005-abstract.html
> 
> Walter, have you also read it? What do you think?
> 
> Here's a bad summary, if you don't feel like reading 20 pages :)
> 
> References/pointers have two properties, assignability and mutability. 
> Assignability is already handled in D by declaring something const, 
> which prevents reassignment, but there is no notion of immutability.
> 
> Javari introduces a readonly keyword, which applies to a reference. When 
> a reference/pointer is readonly, it means that the data it points and 
> also all transitively reachable data cannot be changed.
> 
> Note that there is no implication that the data will not change through 
> other references.
> 
> And, obviously, you can't assign a readonly reference into a mutable 
> var, and you can do the opposite.
> 
> Well, that's the gist of it, other features in random order include:
> 
> - overloading based on mutability of this:
> 
> class StringWithDate {
>    Date getDate() { return m_date; }
>    //   returns a mutable Date, can be called
>    //   only through a mutable reference
> 
>    readonly Date getDate() readonly { return m_date; }
>    // - the second readonly applies to this
>    // - can be called only through a readonly ref
>    // - the Date returned could still be mutable
>    //   but probably the implementation would dup it first
> }
> 
> 
> - romaybe keyword for simple cases like above:
> 
> romaybe Date getDate() romaybe { return m_date; }
> // is exactly the same as the two funcs above; romaybe
> // basically expands into two methods, one replaces
> // all romaybes with readonly, the other with mutable
> 
> 
> - readonly classes:
> 
> readonly class ConstString { ... }
> // will make all references to ConstString immutable
> // (much like how auto classes work)
> 
> 
> - conceptually, each class definition (say Foo : Bar) produces two new 
> types, "readonly Foo : readonly Bar" and "Foo : readonly Foo, Bar", the 
> first of which only contains readonly methods, while the second contains 
> all others. That makes it trivial to do verification and overloading, 
> and has a nice feature that there is no need to actually compile the 
> readonly version, as all verification is done statically, so there is no 
> increase in code size etc.
> 
> 
> - one can still explicitly allow changing an object's fields even 
> through readonly references, which is useful for things like caching 
> hashcodes, logging, etc., which do not change an object's "abstract 
> state" but do still have side effects
> 
> 
> The problem of having to write two versions of functions, depending on 
> mutability, is somewhat helped by "romaybe", and could be further eased 
> if the compiler did some simple inference on its own:
> 
> - class fields are "important" by default and "ignorable" if they are 
> explicitly declared "mutable" or "readonly" (readonly is ignorable, 
> because it cannot be changed in the first place; mutable actually 
> declares the field to be ignorable)
> 
> - any method that could write to important fields or could call 
> non-readonly method on them is inferred to be mutable, unless specified 
> otherwise
> 
> - other methods are considered readonly, unless specified otherwise
> 
> - "in" parameters are resolved analogous to above, "inout" and "out" 
> default to mutable
> 
> - return values default to mutable
> 
> 
> So, would a system like this be acceptable?
> 
> 
> xs0
I would like it this is how I have been using const in c++



More information about the Digitalmars-d mailing list