digitalmars.D.learn - How to create delegates with an independent scope?
- Vijay Nayar (29/29) Mar 30 2022 Consider the following code example:
- vit (22/52) Mar 30 2022 use two delegates :)
- Vijay Nayar (6/16) Mar 30 2022 Very interesting. Both this and creating a "function creator
- vit (2/19) Mar 30 2022 It is bug: https://issues.dlang.org/show_bug.cgi?id=21929
- Tejas (24/54) Mar 30 2022 You can also use `static foreach` and `alias`, although that will
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?
Mar 30 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?use two delegates :) ```d import std; 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()); } } ```
Mar 30 2022
On Wednesday, 30 March 2022 at 12:53:10 UTC, vit wrote:use two delegates :) ```d (){ // 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"); }(); ```Very interesting. Both this and creating a "function creator function" work, and it seems clear that functions create their own scopes. However, it seems that loops do not, is that correct? Maybe I was thrown off by the surrounding `{ }`, but I had assumed that loops created their own scopes.
Mar 30 2022
On Wednesday, 30 March 2022 at 12:56:39 UTC, Vijay Nayar wrote:On Wednesday, 30 March 2022 at 12:53:10 UTC, vit wrote:It is bug: https://issues.dlang.org/show_bug.cgi?id=21929use two delegates :) ```d (){ // 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"); }(); ```Very interesting. Both this and creating a "function creator function" work, and it seems clear that functions create their own scopes. However, it seems that loops do not, is that correct? Maybe I was thrown off by the surrounding `{ }`, but I had assumed that loops created their own scopes.
Mar 30 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()); } } ```
Mar 30 2022