Is there a way to use non-scalar values in functions with where clauses in Chapel?
Asked Answered
A

1

6

I've been trying out Chapel off and on over the past year or so. I have used C and C++ briefly in the past, but most of my experience is with dynamic languages such as Python, Ruby, and Erlang more recently.

After some exposure to Erlang and its function clauses, I was excited to find out about where clauses in Chapel. However, I've run into a barrier with their use. Learn Chapel in Y minutes contains the following code demonstrating a use of the where clause:

proc whereProc(param N : int): void
  where (N > 0) {
    writeln("N is greater than 0");
}

proc whereProc(param N : int): void
  where (N < 0) {
    writeln("N is less than 0");
}

whereProc(10);
whereProc(-1);

This produces the expected output for each of the two scalar values, 10 and -1. However, I have tried to write similar programs that iterate over a range or an array. I've even tried recursion. In all cases I get essentially the same error:

whereproc2.chpl:12: error: unresolved call 'whereProc(int(64))'
whereproc2.chpl:1: note: candidates are: whereProc(param N: int)
whereproc2.chpl:6: note:                 whereProc(param N: int)

The code that produced this particular error is:

proc whereProc(param N : int): void
  where (N > 0) {
    writeln("N is greater than 0");
}

proc whereProc(param N : int): void
  where (N <= 0) {
    writeln("N is less than or equal to 0");
}

for n in 1..10 do
  whereProc(n);

Is there something I'm missing that will cause this to work, or is this not expected to work? I noticed that on Learn Chapel in Y minutes it says all information needs to be known at compile time. Are the contents of a finite range or initialized array not known at compile time? It seems to me that the usefulness of the where clause is limited if it only works with scalar values.

Antoninaantonino answered 23/4, 2018 at 23:15 Comment(0)
M
4

Is there something I'm missing that will cause this to work...?

Yes, the problem is that in your for loop:

for n in 1..10 do
  whereProc(n);

when iterating over ranges, the loop index variable n is an execution-time constant, which prevents the compiler from reasoning about it. In order to get the behavior you want, you need to request that the compiler make it a param (a compile-time constant). This can be done using the syntax:

for param n in 1..10 do
  whereProc(n);

This has the effect of making n a param value which gives the compiler the ability to reason about its value. Try this version of the code online (with a slightly more interesting range).

Using a param index expression like this can be viewed as fully unrolling the loop:

{
  param n = 1;
  whereProc(n);
}
{
  param n = 2;
  whereProc(n);
}
...
{
  param n = 10;
  whereProc(n);
}

As such, this can be a useful idiom for iterating over things when types might vary from one iteration to the next (like a heterogeneous tuple).

Melanie answered 23/4, 2018 at 23:46 Comment(1)
Adding to my response above, I'll note that, at present, Chapel is fairly limited in terms of the types of variables that can be represented as param values, which will in turn limit what you can express in a where clause. This restriction is based on the kinds of values that our compiler can currently reason about, and it is a restriction that we hope to reduce/remove in the future.Melanie

© 2022 - 2024 — McMap. All rights reserved.