On 06/19/12 19:30, Christophe Travert wrote:
> Artur Skawina , dans le message (digitalmars.D:170175), a écrit :
>> On 06/19/12 15:29, deadalnix wrote:
>>> Le 19/06/2012 14:30, Artur Skawina a écrit :
>>>>> Due to D concept of weak purity, this doesn't ensure the required what we
>>>>> need here.
>>>>
>>>> Actually, it does - if it can be proved that the delegate can't alter the
>>>> object
>>>> via the context pointer (eg because whatever it points to is not mutable)
>>>> then
>>>> even D's "pure" is enough. Because the delegate would need to be passed a
>>>> mutable
>>>> ref to be able to alter the object, which then could hardly be constructed
>>>> as
>>>> "breaking" constness.
>>>>
>>>> But such a limit (const/immutable context) would be a problem for the
>>>> cases where
>>>> the delegate needs to alter some state (like export the result of some
>>>> operation),
>>>> but does _not_ modify the object it's embedded in. Note that the current
>>>> object may
>>>> very well be reachable (and mutable) from the delegate - but at some point
>>>> you have
>>>> to trust the programmer. Sure, fixing this hole would be great, but /how/
>>>> - w/o
>>>> incurring unacceptable collateral damage?
>>>>
>>>
>>> This isn't a problem as long as the delegate isn't a member of the object.
>>> If it is, transitivity is broken, which is something you don't want.
>>>
>>> Relying on the trust on the programmer is a dumb idea. Human do mistake,
>>> way more than computers. The basic behavior MUST be a safe one.
>>>
>>> Transitivity has been introduced for good reason and language already
>>> provide a way to break it via cast. So it is unacceptable to rely on
>>> programmer on that point.
>>>
>>>>> It is possible to get the error when trying to call the delegate instead
>>>>> of preventing to make it const, as I said in the post you quote. It is
>>>>> probably a better solution.
>>>>
>>>> Any delegate?
>>>>
>>>
>>> No, any delegate that have type that isn't covariant with the expected
>>> delegate type.
>>
>> struct S {
>> int i; this(int i) { this.i = i; }
>> T* p;
>> void f(int i) { this.i = i; /*p.i++;*/ }
>> }
>> struct T {
>> int i; this(int i) { this.i = i; }
>> void delegate(int i) f;
>> }
>>
>> void main() {
>> auto t = new T(42);
>> auto s = new S(17);
>> s.p = t;
>> t.f = &s.f;
>> f(t);
>> }
>>
>> void f(const (T)* t) {
>> t.f(t.i*2);
>> }
>>
>> You're proposing to make the last 'f' function illegal, just because the
>> commented out part could happen. I'm saying that this is unlikely to happen
>> *by accident*, and of course would still be possible by casting away the
>> constness.
>> But banning "unsafe" delegates would result in casts *when using "safe" ones*
>> - which is not a real improvement because this would make the "bad" casts
>> much
>> harder to spot.
>
>
> The proper way to do this is not cast, it is to give the proper
> constness for all types and methods :
>
> struct S {
> int i; this(int i) { this.i = i; }
> T* p;
> void f(int i) const { this.i = i; /*p.i++;*/ }
> // the commented part is illegal because S.f is const
Not just the commented part.
> }
> struct T {
> int i; this(int i) { this.i = i; }
> void delegate(int i) const f;
> // T.f is const to be callable from .f
> }
>
> void main() {
> auto t = new T(42);
> auto s = new S(17);
> s.p = t;
> t.f = &s.f; // legal when T.f is const because S.f is also const
Only a const T.f would be pointless.
Like I've already said twice in this thread - it *can* be done (the
function has to be "pure" too for it to work), but certain delegate
uses, which are OK now, would be forbidden.
I'm all for fixing this hole - it's just that the proposed "fix" would
have consequences, which can't simply be ignored.
Language design is not a game of whack-a-mole, where you ban random
features left and right, because you think you've noticed a problem,
without properly identifying it nor spending even a single second
figuring out the implications.
artur