I am trying to pass a function mult10
to another function and ask some calculation. Here,mult10
is a test function that receives a one-dimensional array and multiplies their elements by 10. But the compilation fails with an internal error. I also tried attaching one of ref
, in
, out
, inout
(disregarding their meaning anyway), but all of them result in the same internal error.
My motivation for this code is to pass a function with an array argument to a different routine and set the calculated result to the array in-place (rather than getting the result as a function return value).
Source Code:
// test1.chpl
proc mult10( arr : [] int ) {
arr *= 10;
}
proc test( f ) {
var A : [1..5] int = 5;
f( A );
writeln( A );
}
// This part works
var B : [1..7] int = 7;
mult10( B );
writeln( B ); // -> 70 70 70 70 70 70 70
// This line results in internal error
test( mult10 );
Because the mult10()
above may be still "generic" (by being able to receive an arbitrary dimensional array), I also tried making it a specific function somehow. First, this "test2.chpl"
// test2.chpl
proc mult10( arr : [domain(1,int(64),false)] int(64) ) {
arr *= 10;
}
// (the remaining part is the same)
fails with a compilation error (probably because my specification of array type is wrong...), while "test3.chpl" below works somehow (although I am not sure whether the use of [1..1] for array1Dint
is reasonable or not).
// test3.chpl
var array1Dint: [1..1] int;
proc mult10( arr : array1Dint.type ) {
arr *= 10;
}
// (the remaining part is the same)
Compile command:
chpl test.chpl
Error message:
test1.chpl:2: In function 'mult10':
test1.chpl:2: internal error: CAL0124 chpl version 1.18.0
Internal errors indicate a bug in the Chapel compiler ("It's us, not you"),
and we're sorry for the hassle. We would appreciate your reporting this bug --
please see https://chapel-lang.org/bugs.html for instructions. In the meantime,
the filename + line number above may be useful in working around the issue.
Output of chpl --version
:
chpl version 1.18.0
Output of $CHPL_HOME/util/printchplenv --anonymize
:
CHPL_TARGET_PLATFORM: darwin
CHPL_TARGET_COMPILER: clang
CHPL_TARGET_ARCH: native
CHPL_LOCALE_MODEL: flat
CHPL_COMM: none
CHPL_TASKS: qthreads
CHPL_LAUNCHER: none
CHPL_TIMERS: generic
CHPL_UNWIND: none
CHPL_MEM: jemalloc
CHPL_ATOMICS: intrinsics
CHPL_GMP: none
CHPL_HWLOC: hwloc
CHPL_REGEXP: none
CHPL_AUX_FILESYS: none
Output of clang --version
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
@ty1027 - first class functions are missing a lot of functionality and design right now. This is a known issue and will take some time to solve. It's described in #8351 but and for now we are prioritizing other things above improving the situation.
Something that works much better in the current compiler is to use a "function object". This term is borrowed from C++. The idea is to create a record or a class that implements the this
method which means that it can be syntactically called like a function. But in fact this just translates into calling the this
method.
For example, here is a working version of your program using this approach:
record Mult10 {
proc this( arr : [] int ) {
arr *= 10;
}
}
proc test( f ) {
var A : [1..5] int = 5;
f( A );
writeln( A );
}
// This part works
var B : [1..7] int = 7;
var mult10 = new Mult10();
mult10(B);
writeln( B ); // -> 70 70 70 70 70 70 70
// This line results in internal error
test( mult10 );
When using this function object approach, the expectation is that you'd explicitly store any state the function needs (state that with first class functions you could encode by referring to outer variables). This state needs to be stored as fields in the record or class defining the function object.
@mppf Thanks very much for suggesting a workaround approach (= function object). I have just tried it on my machine, and it seems to work very nicely. In my actual code, I need to pass various functions that calculate energy and gradient vector in-place, which should be straightforward if the above Mult10 case works. Thanks much!
@ty1027 - glad your immediate problem is solved. Let's leave this and the other issue open for whenever we fix up first class functions. I'd still like those to work one day as they're simpler to write.