Building a first-class function with a variable-length array argument is possible

The following code fails at compilation (using chapel 1.33):

proc g(a: [] real): real {
   var s = 0.0;
   for e in a do {
      s += e ;
   }
   return s;
}
proc f(ref a: [] real, const g: proc(x: [] real)) {
   if g(a) > 0.0 then {
      writeln("sum is positive");
   }
   else if g(a) ==  0.0 then {
      writeln("sum is zero");
   }
   else {
      writeln("sum is negative");
   }
}
var a = [1.0,2.0,-3.0];
f(a,g);

because a in g is an array argument (from the chapel documentation):

"A function is generic if any of the following conditions hold:
...
The type of some formal argument is an array type where either the
element type is queried or omitted or the domain is queried or
omitted."

Hence g is generic and not a first-class function, and cannot be used as argument in another function f

I have found however that this alternative works fine:

record vla {
   var dom: domain(1);
   var arr: [dom] real;
   proc ref this(k:int) ref {
      return arr[k];
   }
}
proc g(ref a: vla): real {
   var s = 0.0;
   for i in a.dom do {
      s += a[i];
   }
   return s;
}
proc f(ref a: vla, const g: proc(ref x: vla)) {
   if g(a) > 0.0 then {
      writeln("sum is positive");
   }
   else if g(a) ==  0.0 then {
      writeln("sum is zero");
   }
   else {
      writeln("sum is negative");
   }
}
var a = new vla({1..3},[1.0,2.0,-3.0]);
f(a,g);

This is very useful, since in numerical methods there are times when you need to say something like f(a,g) where a is an array that will be used by g (think of Runge-Kutta to solve systems of ODEs). I think that this approach is good enough for my needs, and may help others as well, so I decided to post it here. Merry Xmas,

Nelson

Hi @nelsonluisdias - thanks for the note!

Indeed, this is a useful pattern. I usually call this pattern using a "function object" following the C++ terminology.

We would like to support generic first-class functions. We are just not there yet.

Best,

-michael