Jump to page: 1 2
Thread overview
Try blocks are trying
Oct 10, 2021
Carl Sturtivant
Oct 10, 2021
jfondren
Oct 10, 2021
Imperatorn
Oct 10, 2021
Greg Strong
Oct 10, 2021
Ali Çehreli
Oct 11, 2021
FeepingCreature
Oct 11, 2021
Imperatorn
Oct 11, 2021
FeepingCreature
Oct 11, 2021
Imperatorn
Oct 11, 2021
FeepingCreature
Oct 11, 2021
bauss
Oct 11, 2021
FeepingCreature
Oct 11, 2021
bauss
Oct 11, 2021
FeepingCreature
Oct 11, 2021
Paul Backus
Oct 11, 2021
FeepingCreature
Oct 11, 2021
Paul Backus
Oct 12, 2021
FeepingCreature
Oct 11, 2021
Imperatorn
October 10, 2021

Why is it that a try block is defined to establish a scope?

    try {
        auto x = frgl();
    }
    // ...
    // x undefined here

What is the benefit of this? If try (like static if/foreach) did NOT establish a scope, then this annoyance would go away. And if a scope was desired for some reason, then an extra pair of braces could be written within.

Right now rewriting the above requires getting the return type of frgl and declaring x to be of that type before the try block.

Design error?

October 10, 2021

On Sunday, 10 October 2021 at 16:12:31 UTC, Carl Sturtivant wrote:

>

Design error?

A block not introducing a scope is weird, and my first reaction to the {{ }} workaround was disgust. That's with version and static foreach blocks where not introducing a scope has very clear benefits. Try/catch meanwhile is a familiar construct and people are already used to working around issues like this.

typeof(frgl()) x;
try {
    x = frgl;
} catch (Exception e) { }

I'd consider also if you can use std.exception.ifThrown or a scope statement instead:

auto x = frgl().ifThrown(typeof(frgl()).init);
October 10, 2021

On Sunday, 10 October 2021 at 16:12:31 UTC, Carl Sturtivant wrote:

>

Why is it that a try block is defined to establish a scope?

    try {
        auto x = frgl();
    }
    // ...
    // x undefined here

What is the benefit of this? If try (like static if/foreach) did NOT establish a scope, then this annoyance would go away. And if a scope was desired for some reason, then an extra pair of braces could be written within.

Right now rewriting the above requires getting the return type of frgl and declaring x to be of that type before the try block.

Design error?

Sidenote, do you know about scope guard?
https://tour.dlang.org/tour/en/gems/scope-guards

October 10, 2021

On Sunday, 10 October 2021 at 16:12:31 UTC, Carl Sturtivant wrote:

>

Why is it that a try block is defined to establish a scope?

    try {
        auto x = frgl();
    }
    // ...
    // x undefined here

What is the benefit of this? If try (like static if/foreach) did NOT establish a scope, then this annoyance would go away. And if a scope was desired for some reason, then an extra pair of braces could be written within.

Right now rewriting the above requires getting the return type of frgl and declaring x to be of that type before the try block.

Design error?

One of the main reasons to use a try block is to ensure a destructor is called at the end of the try block. If try didn't create a new scope, these things don't go out of scope, so they wouldn't be cleaned up.

October 10, 2021
On 10/10/21 9:12 AM, Carl Sturtivant wrote:
> Why is it that a try block is defined to establish a scope?
>
> ```
>      try {
>          auto x = frgl();
>      }
>      // ...
>      // x undefined here
>
> ```

One more point in favor of the current semantics, which your code seems to be in support of: x may be left in a state that does not provide its invariants.

I am thinking out loud now: Luckily (and of course by good design), scope(failure) cannot be used in bad state either because in that case x must have already been defined when the scope(failure) appears in code:

  scope(failure) {
    writeln(x);  // Compilation error (undefined x)
  }
  auto x = frgl();

And the following does not execute the scope(failure) block if frgl() throws because scope(failure) code is not "registered" yet:

  auto x = frgl();
  scope(failure) {
    writeln(x);  // Not executed if frgl() throws
  }

Ok, I think we are in good shape with scope(failure) as well. :)

Ali

October 11, 2021

On Sunday, 10 October 2021 at 16:12:31 UTC, Carl Sturtivant wrote:

>

Why is it that a try block is defined to establish a scope?

    try {
        auto x = frgl();
    }
    // ...
    // x undefined here

What is the benefit of this? If try (like static if/foreach) did NOT establish a scope, then this annoyance would go away. And if a scope was desired for some reason, then an extra pair of braces could be written within.

Right now rewriting the above requires getting the return type of frgl and declaring x to be of that type before the try block.

Design error?

I do not deny that my heart has greatly desired this.

Proposal:

export try {
    auto x = frgl();
}
catch (Exception) {
    return false;
}

shall be equivalent to

typeof(frgl()) x = void;
try {
    frgl().moveEmplace(x);
}
catch (Exception) {
    __EXCEPTION_BODY__
    assert(false, "`export` specified: all catch blocks must exit scope");
}
POST

Here, auto frgl dominates POST and is thus correct.

Scope guards directly in try{} should be lifted into the surrounding context, but this is confusing, so they are an error.

October 11, 2021

On Sunday, 10 October 2021 at 16:12:31 UTC, Carl Sturtivant wrote:

>

Why is it that a try block is defined to establish a scope?

    try {
        auto x = frgl();
    }
    // ...
    // x undefined here

What is the benefit of this? If try (like static if/foreach) did NOT establish a scope, then this annoyance would go away. And if a scope was desired for some reason, then an extra pair of braces could be written within.

Right now rewriting the above requires getting the return type of frgl and declaring x to be of that type before the try block.

Design error?

In that case you would just declare x outside and do the call in the try

October 11, 2021

On Monday, 11 October 2021 at 08:55:56 UTC, Imperatorn wrote:

>

In that case you would just declare x outside and do the call in the try

Thus once again demonstrating that for a language that had a major version change over it, D2 really doesn't care about immutable.

October 11, 2021

On Monday, 11 October 2021 at 09:21:48 UTC, FeepingCreature wrote:

>

On Monday, 11 October 2021 at 08:55:56 UTC, Imperatorn wrote:

>

In that case you would just declare x outside and do the call in the try

Thus once again demonstrating that for a language that had a major version change over it, D2 really doesn't care about immutable.

I don't know about that. But it's pretty standard for try to introduce a scope.

October 11, 2021

On Monday, 11 October 2021 at 09:23:27 UTC, Imperatorn wrote:

>

On Monday, 11 October 2021 at 09:21:48 UTC, FeepingCreature wrote:

>

On Monday, 11 October 2021 at 08:55:56 UTC, Imperatorn wrote:

>

In that case you would just declare x outside and do the call in the try

Thus once again demonstrating that for a language that had a major version change over it, D2 really doesn't care about immutable.

I don't know about that. But it's pretty standard for try to introduce a scope.

The problem is if you want to use immutable types at all, this forces you to either use awkward nested function idioms with tuple returns for more than one variable, put the entire remaining function body in the try block. It makes it impossible to keep try small.

One possible solution would be a way to try/catch as an expression:

auto x = frgl().tryCatch(Exception exc: return exc;);

But D has no precedent for statements embedded in expressions like this, so it'd be a major language shift.

export try is the only feasible approach I can see offhand.

« First   ‹ Prev
1 2