On Sunday, 24 January 2016 at 06:07:13 UTC, Alex Vincent wrote:
(1) It's not clear how to specify certain parts of a module or library as non-exportable. Is that possible? Is it desirable?
 (It's not that important, yet, but still...)

Yes, definitely. By default symbols in a module are `public`, but you can mark them as `private`. These aren't accesible from other modules:

    module test;

    void foo() { }        // public, because there's no annotation
    private bar() { }     // private
    void bar2() { }       // public again

    private:              // everything from here on is private
    void bla() { }
    void blubb() { }


(2) In the unittest code, I have a block that I want to rewrite using assertThrown, but I can't figure out from either the book or the website the correct usage. What's the right way to specify a StringException with a particular message I expect to receive?

Here's the relevant documentation:
https://dlang.org/phobos/std_exception.html#.assertThrown
https://dlang.org/phobos/std_exception.html#.collectExceptionMsg

`assertThrown()` doesn't allow to check the message directly, it can only check whether a particular type of exception has been thrown:

assertThrown!StringException(throw new StringException("test"));

Instead, you can use `collectExceptionMsg()` to check both the message and the exception type:

    assert(
        collectExceptionMsg!StringException(throw ...) == "test"
    );


(4) How should the scope(exit) and scope(failure) guard statements intermix with preconditions and postconditions?

Pre- and postconditions are supposed to run before you enter the function, or after you left it, respectively. Therefore, and scope() blocks in the function body would already have completed when the postcondition is entered. OTOH, scope() blocks only run if control flow has passed through them. In a precondition, this hasn't happened yet, and therefore they will not run.

If you mean whether you can use scope() blocks in pre- and postconditions, yes, you can. The will then run when you leave the pre- and postcondition. But usually, pre- and postconditions only consist of very little code that's not supposed to do any serious work, so they are less likely to be used there.

Or, looking at it from a different angle: A scope() block only runs at the end of the lexical scope / block it appears in. Pre- and postconditions are not part of the function body, or vice versa. Therefore, see above.


(5) My append() function has a postcondition that currently depends on debug-only members of the class being set in the precondition. This seems artificial - not the part about setting these variables in the precondition, but having the variables defined on the class to begin with. If they were defined only for the lifetime of the function's execution, starting in the precondition, this would be more natural. Is there a Right Way to define function-only debug variables for use in postconditions? If not, would this be a valid use-case to consider amending the language specification to clarify?

I'm not an expert in contract programming, but as I see it, your precondition doesn't actually check anything, you're kinda abusing them as preparation for your postcondition. That's likely not the way it's supposed to be. I see what you're trying to achieve, and I believe it's legitimate to check for... You could either just move the assert()s into the function body just before the end, where you have access to the local variables (but you could easily miss an early return), or put them into a scope(exit) block (but then you could accidentally check it too early). Your best bet here is probably to check it in a unittest, although they are for a slightly different purpose, strictly speaking.

Reply via email to