Writing const-correct code in D
xs0
xs0 at xs0.com
Wed Mar 8 04:05:45 PST 2006
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
More information about the Digitalmars-d
mailing list