Re: How to create delegates with an independent scope?

2022-03-30 Thread Tejas via Digitalmars-d-learn

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());
  }
}
```



Re: How to unit-test behavior under "version"?

2022-03-30 Thread Andrey Zherikov via Digitalmars-d-learn

On Wednesday, 30 March 2022 at 04:15:24 UTC, Paul Backus wrote:

Probably the easiest way is to split it into two functions

```d
void f()
{
version (foo)
fVersionFoo();
else
fDefault();
}

void fVersionFoo()
{
/* ... */
}

void fDefault()
{
/* ... */
}
```

Then you can write separate unit tests for both `fVersionFoo` 
and `fDefault`, and they will both be tested regardless of what 
settings you build with.


This is an option when you have big difference between foo and 
not-foo behavior. In my case they are 90% the same so I think 
I'll go this way:


```d
void fImpl(bool fooMode)()
{
static if(fooMode)
writeln("foo");
else
writeln("no foo");
}

version(foo)
alias f = fImpl!true;
else
alias f = fImpl!false;

unittest {
// test fImpl!true
}
unittest {
// test fImpl!false
}
```



Re: How to create delegates with an independent scope?

2022-03-30 Thread vit via Digitalmars-d-learn

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:

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.


It is bug: https://issues.dlang.org/show_bug.cgi?id=21929



Re: How to create delegates with an independent scope?

2022-03-30 Thread Vijay Nayar via Digitalmars-d-learn

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.


Re: How to create delegates with an independent scope?

2022-03-30 Thread vit via Digitalmars-d-learn

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());
}
}
```



How to create delegates with an independent scope?

2022-03-30 Thread Vijay Nayar via Digitalmars-d-learn

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?