Thread overview
Capturing a variable by value?
Feb 03, 2016
ZombineDev
Feb 03, 2016
ZombineDev
Feb 03, 2016
Basile B.
Feb 03, 2016
Ali Çehreli
February 03, 2016
C++11 allows you to capture a local variable explicitly by value.

What is the simplest way to make code below print "0 1 .. 9", like the C++ version does?

D version:
```
import std.stdio;

void main()
{
    alias F = void delegate();
	
    F[] arr;
	
    foreach (i; 0 .. 10)
        arr ~= { write(i, " "); };
			
    foreach (f; arr)
        f();
}
```
Prints: 9 9 9 9 9 9 9 9 9 9


C++ version:
```
#include <iostream>
#include <functional>
#include <vector>
using namespace std;

int main()
{
    using F = function<void()>;

    vector<F> arr;

    for (auto i = 0; i < 10; ++i)
        arr.push_back([=]() { cout << i << " "; });

    for (auto f : arr)
        f();
}
```
Prints: 0 1 2 3 4 5 6 7 8 9

One stupid solution is to replace `0 .. 10` with staticIota!(0, 10), which would unroll the loop at CT, but I want something more general that would me allow me to capture the values of a range while iterating over it at run-time.
February 03, 2016
On Wednesday, 3 February 2016 at 18:03:24 UTC, ZombineDev wrote:
> C++11 allows you to capture a local variable explicitly by value.
>
> What is the simplest way to make code below print "0 1 .. 9", like the C++ version does?
>
> D version:
> ```
> import std.stdio;
>
> void main()
> {
>     alias F = void delegate();
> 	
>     F[] arr;
> 	
>     foreach (i; 0 .. 10)
>         arr ~= { write(i, " "); };
> 			
>     foreach (f; arr)
>         f();
> }
> ```
> Prints: 9 9 9 9 9 9 9 9 9 9
>
>
> C++ version:
> ```
> #include <iostream>
> #include <functional>
> #include <vector>
> using namespace std;
>
> int main()
> {
>     using F = function<void()>;
>
>     vector<F> arr;
>
>     for (auto i = 0; i < 10; ++i)
>         arr.push_back([=]() { cout << i << " "; });
>
>     for (auto f : arr)
>         f();
> }
> ```
> Prints: 0 1 2 3 4 5 6 7 8 9
>
> One stupid solution is to replace `0 .. 10` with staticIota!(0, 10), which would unroll the loop at CT, but I want something more general that would me allow me to capture the values of a range while iterating over it at run-time.

I think these two links, more or less, answer my question:
http://stackoverflow.com/questions/29759419/closures-in-loops-capturing-by-reference
https://issues.dlang.org/show_bug.cgi?id=2043
February 03, 2016
On Wednesday, 3 February 2016 at 18:09:52 UTC, ZombineDev wrote:
> I think these two links, more or less, answer my question:
> http://stackoverflow.com/questions/29759419/closures-in-loops-capturing-by-reference
> https://issues.dlang.org/show_bug.cgi?id=2043

Another approach:

import std.range, std.array, std.stdio;

struct InputRangeHook(T, alias Fun)
if (isInputRange!T)
{
    private T _t;
    this(T t)
    {
        _t = t;
    }
    void popFront()
    {
        Fun(front());
        _t.popFront;
    }
    bool empty()
    {
        return _t.empty();
    }
    auto front()
    {
        return _t.front;
    }
}

void main()
{
    foreach(i; InputRangeHook!(int[],(a) {write(a," ");})(iota(0,10).array)){}
}
February 03, 2016
On 02/03/2016 10:09 AM, ZombineDev wrote:

> I think these two links, more or less, answer my question:
> http://stackoverflow.com/questions/29759419/closures-in-loops-capturing-by-reference 

>
> https://issues.dlang.org/show_bug.cgi?id=2043

I find it more readable to give a name like makeClosure():

    foreach (i; 0 .. 10) {
        auto makeClosure = (int a) {
            return { write(a, " "); };
        };

        arr ~= makeClosure(i);
    }

Of course, makeClosure() can be moved out of the loop if needed.

Ali