How to create delegates with an independent scope?

Tejas notrealemail at gmail.com
Wed Mar 30 15:49:24 UTC 2022


On Wednesday, 30 March 2022 at 12:46:07 UTC, Vijay Nayar wrote:
> Consider the following code example:
>
> ```d
> import std.stdio;
>
> void main()
> {
>   alias DelegateT = string delegate();
>
>   // An array of delegates, each has their own scope.
>   DelegateT[] funcs;
>   foreach (i; ["ham", "cheese"]) {
>     // Deliberately create a copy to keep in delegate scope.
>     string myStr = i.dup;
>     // The delegate will hopefully carry this copy around in 
> its own scope.
>     funcs ~= (() => myStr ~ " sandwich");
>   }
> 	
>   foreach (f; funcs) {
>     writeln(f());
>   }
> }
> ```
>
> The expected output is: "ham sandwich" and then "cheese 
> sandwich".
>
> The actual output is: "cheese sandwich" and then "cheese 
> sandwich".
>
> It seems that the variable `myStr` is in a sort of shared scope 
> for both functions in the array, and the last value written to 
> it dominates.
>
> How do I create a delegate that acts like a 
> [closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures), that is, it carries with it the environment in which it was created?

You can also use `static foreach` and `alias`, although that will 
restrict that code to compile time usage only :/

```d
import std;
import std.stdio;

void main()
{
   alias DelegateT = string delegate();

   // An array of delegates, each has their own scope.
   DelegateT[] funcs;
   static foreach (alias i; ["ham", "cheese"]) {
     // Deliberately create a copy to keep in delegate scope.
     //string myStr = i.dup;
     // The delegate will hopefully carry this copy around in its 
own scope.
     funcs ~= (() => /*myStr*/ i ~ " sandwich");
   }
	
   foreach (f; funcs) {
     writeln(f());
   }
}
```



More information about the Digitalmars-d-learn mailing list