Thread overview
How to do conditional scope(exit) ?
4 days ago
John Dougan
4 days ago
monkyyy
4 days ago
mzfhhhh
3 days ago
kdevel
4 days ago

As the subject. The obvious way:

import std;

int test(int val)
{
    writeln("A");
    if (val % 2 == 0)
    {
        writeln("b");
        scope (exit)
            writeln("scope exit ", val);
        writeln("c");
    }
    writeln("F");
    return 2 * val;
}

void main()
{
    writeln("== start =========================");
    int v1 = test(1);
    writeln("== 2 ==============================");
    int v2 = test(2);
    writeln("== end ===========================");
}

results in:

== start =========================
A
F
== 2 ==============================
A
b
c
scope exit 2
F
== end ===========================

which isn't what I want. The case for test(1) is fine. For test(2)) I want the scope exit 2 to come after the F. Is there a way to tell it that I want to use an enclosing scope or make it ignore the scope on the if?

Cheers,
-- John

4 days ago

On Wednesday, 18 December 2024 at 22:16:45 UTC, John Dougan wrote:

>

Is
there a way to tell it that I want to use an enclosing scope or make it ignore the scope on the if?

Cheers,
-- John

I dont think its anywhere near that smart, ive never seen a single usecase of scope(exit) do anything of note

4 days ago
On Wednesday, December 18, 2024 3:16:45 PM MST John Dougan via Digitalmars-d-learn wrote:
> As the subject. The obvious way:
>
> ```D
> import std;
>
> int test(int val)
> {
>      writeln("A");
>      if (val % 2 == 0)
>      {
>          writeln("b");
>          scope (exit)
>              writeln("scope exit ", val);
>          writeln("c");
>      }
>      writeln("F");
>      return 2 * val;
> }
>
> void main()
> {
>      writeln("== start =========================");
>      int v1 = test(1);
>      writeln("== 2 ==============================");
>      int v2 = test(2);
>      writeln("== end ===========================");
> }
> ```
> results in:
>
> ```
> == start =========================
> A
> F
> == 2 ==============================
> A
> b
> c
> scope exit 2
> F
> == end ===========================
> ```
>
> which isn't what I want. The case for `test(1)` is fine. For
> `test(2))` I want the  `scope exit 2` to come after the `F`. Is
> there a way to tell it that I want to use an enclosing scope or
> make it ignore the scope on the `if`?

scope statements are run when the scope that they're in exits (with scope(exit) always running, scope(failure) running only when the scope is exited via an exception being thrown, and scope(success) only being run when no exception is thrown). There is no way to control whether they run beyond whether it's exit, failure, or success, and trying to insert if statements around scope statements is just going to change which scope that they refer to, since you can't put a scope statement in an inner scope and then have it be run for an outer scope. It's always for the scope that the scope statement is in.

Now, you _can_ put an if statement within the scope statement to control what's run within the scope statement, but that condition will be checked when the scope statement is run. So, you may be able to get what you want that way, but scope statements themselves are quite simple and not particularly flexible. Ultimately, they're just a way to not have to manually write a try-catch block when you don't care about actually looking at the exception being thrown and just want to write code that runs or doesn't run based on whether the scope is exited normally or via an exception being thrown.

One thing to remember is that scope statements are implemented as try-catch blocks. So, if you have something like

{
    scope(exit) doStuff();
    runCode();
}

it'll be lowered to something along the lines of

{
    try
    {
        runCode();
        doStuff();
    }
    catch(Exception e)
    {
        doStuff();
        throw e;
    }
}

and

{
    scope(failure) doStuff();
    runCode();
}

will be lowered to something like

{
    try
    {
        runCode();
    }
    catch(Exception e)
    {
        doStuff();
        throw e;
    }
}

whereas

{
    scope(success) doStuff();
    runCode();
}

will be lowered to something like

{
    runCode();
    doStuff();
}

So, when you're considering what can or can't be done with scope statements, thinking about how they're lowered to try-catch blocks may help you understand why they work the way that they do. And if you can't do what you want to do with a try-catch block, then you definitely can't do it with scope statements, since that's what they ultimately are.

- Jonathan M Davis



4 days ago

On Wednesday, 18 December 2024 at 22:16:45 UTC, John Dougan wrote:

>

As the subject. The obvious way:
I want the scope exit 2 to come after the F. Is there a way to tell it that I want to use an enclosing scope or make it ignore the scope on the if?

Cheers,
-- John

This code can make "scope exit 2" be output at the end.

import core.stdc.stdio;
import std;

enum exitcb = `scope void delegate() exitcb;
scope(exit) if(exitcb) exitcb();`;

int test(int val)
{
    mixin (exitcb);

    writeln("A");
    if (val % 2 == 0)
    {
        writeln("b");
        scope (exit)
           exitcb = { writeln("scope exit ", val); };
        writeln("c");
    }
    writeln("F");
    return 2 * val;
}

void main()
{
    writeln("== start =========================");
    int v1 = test(1);
    writeln("== 2 ==============================");
    int v2 = test(2);
    writeln("== end ===========================");
}
3 days ago

On Wednesday, 18 December 2024 at 22:16:45 UTC, John Dougan wrote:

>

[...]
which isn't what I want. The case for test(1) is fine. For test(2)) I want the scope exit 2 to come after the F.

int test(int val)
{
    writeln("A");
    if (val % 2 == 0)
    {
        writeln("b");
        scope (exit)
            writeln("scope exit ", val);
        writeln("c");
        writeln("F");
    }
    else
        writeln("F");
    return 2 * val;
}

results in

== start =========================
A
F
== 2 ==============================
A
b
c
F
scope exit 2
== end ===========================

>

Is there a way to tell it that I want to use an enclosing scope or make it ignore the scope on the if?

Pardon, can you rephrase your question?