www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - array of delegates

reply Alex <sascha.orlov gmail.com> writes:
Hi at all!
Having read this:
http://forum.dlang.org/post/mailman.2415.1354291433.5162.digitalmars-d-learn puremagic.com

still have a problem...
Lets begin with what works:

enum Props{p1, p2}

class AA
{
     int[] arr1;
     int[] arr2;
     this()
     {
         //arbitrary values...
         arr1 = [9, 6, 33, 42, 58];
         arr2 = [2, 3, 44, 28, 77];
     }

     auto Foo(int i, Props p)
     {
         with(Props)
         {
             final switch(p)
             {
                 case p1:
                     { return arr1[i]; }
                 break;
                 case p2:
                     { return arr2[i]; }
                 break;
             }
         }
     }
}

main()
{
     int indarr[] = [0, 1, 2, 3, 4];
     import std.stdio;
     import std.functional;
     AA aa = new AA();
     int delegate(int, Props) sg;
     sg = &aa.Foo;
     alias M3 = partial!(sg, 3);
     writeln(M3(Props.p1));
     writeln(M3(Props.p2));
}

So far, so good. But now the question:
if I try

import std.algorithm;
indarr.map!(a => partial!(sg, a));

I get an error, like Error: partial (Props _param_0) is not 
callable using argument types ().

Do you have a hint, what I'm doing wrong?

For the motivation: In this way I would like to store some 
"links" to data I have without having to define a struct, which 
incorporate the data.
The struct itself is not the problem, but how the data is handled 
is not known by the struct, but only by the class AA, so the 
expressions inside the switch should not (?) lie inside the 
struct.
Apr 13 2016
next sibling parent reply David Skluzacek <david.skluzacek gmail.com> writes:
So, that message is a pretty cryptic, but the problem there is 
that map does its thing at runtime, but partial is a template and 
must be instantiated at compile time.

Instead you can use std.meta.staticMap, by doing something like 
this:

----

void main()
{
     import std.stdio;
     import std.functional;
     import std.meta;

     AA aa = new AA();
     int delegate(int, Props) sg;
     sg = &aa.Foo;

     template partialSG(alias a)
     {
         alias partialSG = partial!(sg, a);
     }
	
     alias indarr = AliasSeq!(0, 1, 2, 3, 4);
     alias funs = staticMap!(partialSG, indarr);

     foreach (fun; funs)
     {
         writeln( fun(Props.p1) );
         writeln( fun(Props.p2) );
     }
}
Apr 13 2016
parent Alex <sascha.orlov gmail.com> writes:
On Thursday, 14 April 2016 at 05:54:38 UTC, David Skluzacek wrote:
 So, that message is a pretty cryptic, but the problem there is 
 that map does its thing at runtime, but partial is a template 
 and must be instantiated at compile time.

 Instead you can use std.meta.staticMap, by doing something like 
 this:

 ----

 void main()
 {
     import std.stdio;
     import std.functional;
     import std.meta;

     AA aa = new AA();
     int delegate(int, Props) sg;
     sg = &aa.Foo;

     template partialSG(alias a)
     {
         alias partialSG = partial!(sg, a);
     }
 	
     alias indarr = AliasSeq!(0, 1, 2, 3, 4);
     alias funs = staticMap!(partialSG, indarr);

     foreach (fun; funs)
     {
         writeln( fun(Props.p1) );
         writeln( fun(Props.p2) );
     }
 }
Ah, ok... so, it was my mistake due to runtime <-> compile time templates. Thanks. But, this would help, only if I know the total amount of my elements at compile time. Say, the length of the indarr would be known. What if I don't have this information? In reality, this information is already known for the constructors of my classes. But it seems very strange to me, to let the user recompile the program each time with some compiler flag in order to deliver this parameter a step prior to this.
Apr 13 2016
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 04/13/2016 04:39 PM, Alex wrote:

 import std.algorithm;
 indarr.map!(a => partial!(sg, a));
I think you want to generate a different delegate for each element where the first argument to sg is the value of that element (0, 1, etc.). Since the second element of sg is a Props, you then want to call those delegates with a Props value (e.g. Props.p1). The following works: import std.algorithm; auto mapped = indarr .map!(a => (Props p) => sg(a, p)) .map!(d => d(Props.p1)); writeln(mapped); Ali
Apr 13 2016
parent Alex <sascha.orlov gmail.com> writes:
On Thursday, 14 April 2016 at 06:27:29 UTC, Ali Çehreli wrote:
 On 04/13/2016 04:39 PM, Alex wrote:

 import std.algorithm;
 indarr.map!(a => partial!(sg, a));
I think you want to generate a different delegate for each element where the first argument to sg is the value of that element (0, 1, etc.). Since the second element of sg is a Props, you then want to call those delegates with a Props value (e.g. Props.p1). The following works: import std.algorithm; auto mapped = indarr .map!(a => (Props p) => sg(a, p)) .map!(d => d(Props.p1)); writeln(mapped); Ali
Yes exactly! The idea is to save auto mapped = indarr.map!(a => (Props p) => sg(a, p)); for later use and use it then by mapped[someIndex](Props.p1) or mapped[someIndex](Props.p2) when needed. Thank you very much! :)
Apr 13 2016