June 18, 2007
Russ Williams wrote

> This makes senses because copy and identity are issues with multiple solutions -- a shallow copy as done by 'clone' by default may not be enough for instance -- and a compiler cannot be reasonably expected to guess correctly which interpretation is appropriate for a given usage.

Then `old' seems to control a preimplemented simplified memento pattern that is served once and only on function scope entry.

So this seems an application for D's non existing scope guard
  `scope(entry)'

In fact pre- and postconditions seem to be nothing else than blocks
that are injected into the function body by `scope(entry)' and `scope
(exit)' respectively.

If this holds, then a call of the form `old variable' can in
principle be seen as the duality of
  scope(entry){ save( variable);}
injected into the function body and the call `old variable' replaced
by
  recall( variable);

-manfred
June 18, 2007
Manfred Nowak Wrote:
> So this seems an application for D's non existing scope guard
>   `scope(entry)'
I don't know about this nonexisting scope guard, but if it means the programmer has to write explicit code to do it, that's not the good way to do it...

> In fact pre- and postconditions seem to be nothing else than blocks
> that are injected into the function body by `scope(entry)' and `scope
> (exit)' respectively.

They are a little more than that since there are implications for inheritance (a precondition can be weakened in a derived class, and a postcondition can be strengthened in a derived class, which means OR-ing the preconditions of base.f() and derived.f() and AND-ing the postconditions).

That inheritance aspect of DBC is defined in the language and done by the compiler so the programmer doesn't have to write boilerplate code to screw with it.  Similarly "old" should be defined in the language.  As it stands now, D discourages (to put it mildly) one from writing truly useful postconditions on functions which changes the object in a way dependent on the state of the object when the function is called.

E.g. a container class might have a postcondition including the following assertion:

void addFoo(Foo f)
out
{
    assert(fooCount = old(fooCount) + 1);
}

I really don't want to have to write some kind of extra boilerplate code to save the starting value of fooCount in order to express such simple postconditions.
June 18, 2007
Russ Williams wrote:
> Manfred Nowak Wrote:
>> In fact pre- and postconditions seem to be nothing else than blocks that
>> are injected into the function body by `scope(entry)' and `scope (exit)'
>> respectively.
> 
> They are a little more than that since there are implications for inheritance
> (a precondition can be weakened in a derived class, and a postcondition can
> be strengthened in a derived class, which means OR-ing the preconditions of
> base.f() and derived.f() and AND-ing the postconditions).
> 
> That inheritance aspect of DBC is defined in the language and done by the compiler so the programmer doesn't have to write boilerplate code to screw with it.

Yeah, except: http://d.puremagic.com/issues/show_bug.cgi?id=302

-- 
Remove ".doesnotlike.spam" from the mail address.
June 18, 2007
Russ Williams wrote

> but if it means the programmer has to write explicit code to do it, that's not the good way to do it...

I described how `old' might be implemented.

You described that not being forced to write explicit code only holds in trivial cases.

The non trivial cases need more work to be done. In terms of information hiding a construct like `old( clone( a))' seems horrible.

So:
1) What is the right way to have a smooth transition from implicit to
explicit coding?
2) Is explicit coding the `old' pattern even possible without breaking
some OO-requirements?

-manfred
June 18, 2007
Deewiant Wrote:
> Yeah, except: http://d.puremagic.com/issues/show_bug.cgi?id=302

Hmm, that sucks.  I start to get the feeling that DbC is not really taken seriously in D. :(
June 18, 2007
Manfred Nowak Wrote:
> I described how `old' might be implemented.
> 
> You described that not being forced to write explicit code only holds in trivial cases.

Those trivial cases are very common, however.  In the nontrivial cases, the only explicit code would be needing to implement a clone or copy function for the type, which you quite often would already have anyway.  In all cases, you should never have to write additional declarations inside the function just to support expressing what you need in the postcondition.

> The non trivial cases need more work to be done. In terms of information hiding a construct like `old( clone( a))' seems horrible.

Well, ANY mention of private members in the postcondition violates information hiding; such portions of a postcondition would just be sanity checking for the implementer of the function presumably and ideally not displayed by tools that generate a public interface for human readers.

But if there is a public function which returns some complex funky linked graph of objects, I don't see how "old(clone(funkyThing)) violates any kind of information hiding, given that funkyThing is publicly visible.

The problem has been solved and implemented in other languages, e.g. Eiffel, and Lava (a language about which I know practically nothing else, but just found while googling for more info about "old" :)
http://lavape.sourceforge.net/doc/html/DBC.htm
June 19, 2007
Russ Williams wrote:

> Deewiant Wrote:
>> Yeah, except: http://d.puremagic.com/issues/show_bug.cgi?id=302
> 
> Hmm, that sucks.  I start to get the feeling that DbC is not really taken seriously in D. :(

I created a simple metaprogram that adds DbC inheritance and old objects:

http://paste.dprogramming.com/dpu2y075.php

It's just a temporary workaround - the syntax is bad and it does not parse all declarations nicely. Still, better than nothing :)
1 2
Next ›   Last »