www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to do conditional scope(exit) ?

reply John Dougan <jdougan acm.org> writes:
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`?

Cheers,
   -- John
Dec 18
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
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
Dec 18
prev sibling next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Dec 18
prev sibling next sibling parent mzfhhhh <mzfhhhh foxmail.com> writes:
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. ```d 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 ==========================="); } ```
Dec 18
prev sibling parent kdevel <kdevel vogtner.de> writes:
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?
Dec 19