Thread overview
How do I call a context objects destructor or some type of exit() function automatically upon exiting a with {} scope?
April 01

I thought the destructor might automatically be called after with (new Context()) {} but it's not. Is there some sort of entry/exit functions like in Python?

April 01

On Tuesday, 1 April 2025 at 16:54:50 UTC, Daniel Donnelly, Jr. wrote:

>

I thought the destructor might automatically be called after with (new Context()) {} but it's not. Is there some sort of entry/exit functions like in Python?

You've used new, which means it's allocated with the GC. In that case, your destructor is a finalizer and may or may not be called at any point during the program. It's non-deterministic.

If Context is a class, you can do this:

scope ctx = new Context;

This will allocate the class instance on the stack so the destructor will be called when the scope exits. And of course, if it's a struct, then just drop the new.

All of that said, D does have scope guards when you need them:

https://dlang.org/spec/statement.html#scope-guard-statement

April 01
On 4/1/25 10:08 AM, Mike Parker wrote:
> ```
> scope ctx = new Context;
> ```
>
> This will allocate the class instance on the stack so the destructor
> will be called when the scope exits.

Another option is to call the destructor explicitly through destroy():

import std.stdio;

class C {
    ~this() {
        writeln("Goodbye");
    }
}

void foo() {
    auto c = new C();

    scope (exit) {
        destroy(c);    // <-- HERE
    }
}

void main() {
    writeln("Calling foo");
    foo();
    writeln("Exiting main");
}

Ali

April 01

On Tuesday, 1 April 2025 at 17:08:27 UTC, Mike Parker wrote:

>

On Tuesday, 1 April 2025 at 16:54:50 UTC, Daniel Donnelly, Jr. wrote:

>

[...]

You've used new, which means it's allocated with the GC. In that case, your destructor is a finalizer and may or may not be called at any point during the program. It's non-deterministic.

If Context is a class, you can do this:

scope ctx = new Context;

This will allocate the class instance on the stack so the destructor will be called when the scope exits. And of course, if it's a struct, then just drop the new.

All of that said, D does have scope guards when you need them:

https://dlang.org/spec/statement.html#scope-guard-statement

Thank you, that makes sense!

April 01
On Tuesday, 1 April 2025 at 17:33:02 UTC, Ali Çehreli wrote:
> On 4/1/25 10:08 AM, Mike Parker wrote:
> > ```
> > scope ctx = new Context;
> > ```
> >
> > This will allocate the class instance on the stack so the
> destructor
> > will be called when the scope exits.
>
> Another option is to call the destructor explicitly through destroy():
>
> import std.stdio;
>
> class C {
>     ~this() {
>         writeln("Goodbye");
>     }
> }
>
> void foo() {
>     auto c = new C();
>
>     scope (exit) {
>         destroy(c);    // <-- HERE
>     }
> }
>
> void main() {
>     writeln("Calling foo");
>     foo();
>     writeln("Exiting main");
> }
>
> Ali

Thanks! I will try this scope(exit) trick in order to pop the context internally, these contexts hold local variable definitions so of course I would want to pop them.