www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Delegates: Print 0..9

reply unDEFER <undefer gmail.com> writes:
Hello!
Simple using of delegates:

===========

import std.stdio;

void main()
{
     void delegate() functions[];

     foreach (i; 0..10)
     {
         void print()
         {
             writefln("%s", i);
         }

         functions ~= &print;
     }

     foreach (i; 0..10)
     {
         functions[i]();
     }
}
=============

Prints
$ ./delegates.d
9
9
9
9
9
9
9
9
9
9

How to print 0..9?
Dec 01 2016
next sibling parent unDEFER <undefer gmail.com> writes:
Yes, I have found:

=========================

import std.stdio;

void main()
{
     void delegate() functions[];

     foreach (i; 0..10)
     {
         auto get_print(int i)
         {
             void print()
             {
                 writefln("%s", i);
             }

             return &print;
         }

         functions ~= get_print(i);
     }

     foreach (i; 0..10)
     {
         functions[i]();
     }
}
=========================

Thank you!
Dec 01 2016
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/01/2016 11:28 AM, unDEFER wrote:
 Hello!
 Simple using of delegates:

 ===========

 import std.stdio;

 void main()
 {
     void delegate() functions[];

     foreach (i; 0..10)
     {
         void print()
         {
             writefln("%s", i);
         }

         functions ~= &print;
     }

     foreach (i; 0..10)
     {
         functions[i]();
     }
 }
 =============

 Prints
 $ ./delegates.d
 9
 9
 9
 9
 9
 9
 9
 9
 9
 9

 How to print 0..9?
This is a common issue with D and some other languages (as I had learned during a Dart language presentation, of which Dart does not suffer from). All those delegates do close on the same loop variable. You need to produce copies of the variable. First, the scary syntax that produces a lambda from an int: import std.stdio; void main() { // Note: dmd's -de command line switch warned me about the use of // C-style syntax, so I moved the brackets after the type name: void delegate()[] functions; foreach (i; 0..10) { void print(int j) { writefln("%s", j); } functions ~= ((a) => (() => print(a)))(i); // <-- SCARY } foreach (i; 0..10) { functions[i](); } } Better: // Returns a lambda auto makePrinter(int j) { return { // <-- returns a lambda writefln("%s", j); }; } functions ~= makePrinter(i); But of course there are better ways of doing things e.g. producing numbers. Here is one with D's ranges: import std.stdio: writeln; import std.range: iota; import std.algorithm: each; void main() { 10.iota.each!writeln; } Ali
Dec 01 2016
next sibling parent unDEFER <undefer gmail.com> writes:
On Thursday, 1 December 2016 at 20:12:15 UTC, Ali Çehreli wrote:

 First, the scary syntax that produces a lambda from an int:
 ...
 Better:
 ...
All methods.. Thank you!
Dec 01 2016
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 01.12.2016 21:12, Ali Çehreli wrote:
 This is a common issue with D and some other languages (as I had learned
 during a Dart language presentation, of which Dart does not suffer
 from). All those delegates do close on the same loop variable. You need
 to produce copies of the variable.
This is a common misconception. It's an implementation bug. The variables /are/ distinct. It is actually memory corruption. Evidence: import std.stdio; void main(){ int delegate()[] dgs; foreach(immutable i;0..10){ dgs~=()=>i; // i is immutable } foreach(dg;dgs) writeln(dg()); // yet changes dgs=[]; foreach(i;0..10){ int j=i; // creating a new variable dgs~=()=>j; } foreach(dg;dgs) writeln(dg()); // does not help }
Dec 02 2016