July 06, 2017
On Wednesday, 5 July 2017 at 21:05:04 UTC, Ola Fosheim Grøstad wrote:
> On Wednesday, 5 July 2017 at 15:48:33 UTC, Crayo List wrote:
>> What happens to the 3000 direct and indirect calls to open() ?
>>
>> Notice how the 'interface' has not changed, only the implementation.
>
> No, the exception spec is part of the interface whether it is in the function declaration  or not.

I disagree!
Once an interface is defined you should be able to alter the implementation all you want without impacting client code!

>Such a change could be
> fatal in any system.

No idea what you mean here.

> What you should do is to specify what Exceptions are thrown across module borders. That means you should recast the internal exceptions into module-level exceptions.

I don't need to do anything since I don't have a problem. I don't understand what are you helping me with. I pointed out how checked exceptions 'leak' internal implementation, that was all.




July 07, 2017
On Thursday, 6 July 2017 at 14:59:10 UTC, Crayo List wrote:
> On Wednesday, 5 July 2017 at 21:05:04 UTC, Ola Fosheim Grøstad wrote:
>> On Wednesday, 5 July 2017 at 15:48:33 UTC, Crayo List wrote:
>>> What happens to the 3000 direct and indirect calls to open() ?
>>>
>>> Notice how the 'interface' has not changed, only the implementation.
>>
>> No, the exception spec is part of the interface whether it is in the function declaration  or not.
>
> I disagree!
> Once an interface is defined you should be able to alter the implementation all you want without impacting client code!

Correct. And throwing a different kind of exception changes the interface, and *does* impact client code. Consider:

void fun() {
    try {
        gun();
    } catch (GoodException goodEx) {
        // Ignore
    } catch (Exception badEx) {
        FireZeeMissiles();
    }
}

void gun() {
    throw new GoodException ();
}

Now J. Random Programmer decides to change gun()'s implementation:

void gun() {
    throw new BadException();
}

If your assertion that this doesn't change the interface and doesn't impact the client is correct, no missiles will be fired. Sadly, this is not the case, and Switzerland is now wiped off the map.

--
  Biotronic
July 07, 2017
Am Thu, 06 Jul 2017 13:16:23 +0000
schrieb Moritz Maxeiner <moritz@ucworks.org>:

> On Thursday, 6 July 2017 at 11:01:26 UTC, Marco Leise wrote:
> > Am Thu, 06 Jul 2017 01:31:44 +0000
> > schrieb Moritz Maxeiner <moritz@ucworks.org>:
> > 
> >> But to be clear (and the title and description of any DIP
> >> addressing this should reflect this):
> >> These are not checked exceptions, because checked exceptions
> >> would require bar to declare its exception set manually.
> >
> > Yep, absolutely clear. Just like "auto a = 1" does not declare a variable as we all know declarations start with a type.
> 
> Red herring.
> […]
> 
> ---
> void foo() throws AExp throws BExc { ... }
> void bar1() { foo(); } // Checked exceptions require this to
> result in a compilation error
> void bar2() throws AExc throws BExc { foo(); } // this must be
> used for checked exceptions
> ---

You are right, it was a red herring. The code example makes it very obvious that inference means letting the exceptions slip through unchecked and out of main() in the wildest case.

> Invalid premise. The definition of checked exceptions is de facto fixed by Java [1], because it not only coined the term but remains the only major PL to use them.

That's right, but still one can distill general ideas and leave implementations details aside. Pretty much like the Platonic Ideal. Then you look at what the complaints are with the current implementation and see if you can satisfy all sides.

I don't know if this is any good beyond an example of a different implementation of checked exceptions, but here is one option against the "every function in the call chain accumulates more and more 'throws' declarations":

  /**
   * Throws:
   *   ZeroException when i is 0
   *   NonZeroException when i is not 0
   */
  void foo(int i) {
    if (i == 0) throw new ZeroException();
    throw new NonZeroException();
  }

  void bar(int i) @check_exceptions {
    foo(i);  // Error: The following exceptions are not
  handled:
             //     ZeroException thrown from foo() when i is 0
             //     NonZeroException thrown from foo() when i is not 0
  }

I.e. everything stays the same until a programmer needs a verification of what (s)he should/could handle right away, what needs to be wrapped and what can be passed further up the call chain. That's close to impossible now in deeply nested code.

Resource unavailability prone to race conditions can often be handled by asking the user to fix the issue and continue for example (including network, disk space, RAM, video encoding hardware slots, exclusive microphone use).

In other cases an exception is only thrown when an incorrect argument is passed. Knowing (statically) that you pass only good values you can catch the exception and turn it into an assert instead of passing it up the call chain, potentially allowing the caller to be nothrow.
-- 
Marco

July 07, 2017
On Friday, 7 July 2017 at 18:48:31 UTC, Marco Leise wrote:
> Am Thu, 06 Jul 2017 13:16:23 +0000
> schrieb Moritz Maxeiner <moritz@ucworks.org>:
>
> That's right, but still one can distill general ideas and leave implementations details aside. Pretty much like the Platonic Ideal. Then you look at what the complaints are with the current implementation and see if you can satisfy all sides.

The requirement checked exceptions impose on all functions to declare their respective exception set is not an implementation detail, but part of the definition.
With regards to the general ideas: That's what my writing about exception sets, tehir inference, and nothrow analysis were (supposed to be) about.
Unless, however, whatever one eventually tries to get into the language (if that is even attempted) conforms to the preexisting definition of checked exceptions (which I'm as certain as I can reasonably be won't make it into D), calling it that will only serve to cloud the issue and alienate people.
Personally, I would call a system with the exception set of a function being (optionally) declarable as "declarable exceptions", but that might still be too close to "checked exceptions" not to illicit screams of horror.

>
> [...]
>
> I.e. everything stays the same until a programmer needs a verification of what (s)he should/could handle right away, what needs to be wrapped and what can be passed further up the call chain. That's close to impossible now in deeply nested code.

If one replaces the `@check_exceptions` with `nothrow` the above is essentially what one should get if one enhances the (static) nothrow analysis (as I mentioned in an earlier post) to essentially treat a scope implicitly as nothrow if the aggregated exception set (as determined by the compiler) is empty.
Or more succinct: Infer `nothrow` for normal functions, as well.

> In other cases an exception is only thrown when an incorrect argument is passed. Knowing (statically) that you pass only good values you can catch the exception and turn it into an assert instead of passing it up the call chain, potentially allowing the caller to be nothrow.

There are two cases here:
 - the function takes untrusted user data:
   Violations are valid runtime behaviour -> Exceptions, error codes, split in validation and processing function pair with the second being executed only after the first has successfully validated the input data (and thus transformed it into trusted program data), etc.
 - the function takes trusted program data:
   Violations are bugs -> assert, Error, DbC, etc.

1 2 3 4 5 6 7
Next ›   Last »