Related to my previous question, I have tried to make a function present() for checking the presence of an optional argument. However, the following code
proc present( x ) { return x.type != void; }
proc test( a: ?T = _void )
{
writeln();
writeln( "test| a = ", a );
writeln( "test| condition = ", a.type != void );
writeln( "test| present( a ) = ", present( a ) );
if present( a ) // error (Line 1)
// if a.type != void // works (Line 2)
{
a = 10;
}
}
// no optional arg
test();
// pass an optional array
var arr: [1..5] int;
test( a = arr );
writeln();
writeln( "main| arr = ", arr );
gives a compile-time error
mytest.chpl:3: In function 'test':
mytest.chpl:13: error: illegal lvalue in assignment
mytest.chpl:13: error: a void variable cannot be assigned
which says that the line a = 10; is problematic. On the other hand, if I use Line 2 instead of Line 1, the code works as expected:
test| a =
test| condition = false
test| present( a ) = false
test| a = 0 0 0 0 0
test| condition = true
test| present( a ) = true
main| arr = 10 10 10 10 10
Also, if I replace Line 1 or 2 by if isArray( a ), the code also works. Does this mean that we need to let the compiler explicitly know that the line a = 10; is not reached when a is _void? (In other words, is present() not sufficient to let the compiler know it because the test condition is "hidden" inside present()?)
Does this mean that we need to let the compiler explicitly know that the line a = 10; is not reached when a is _void? (In other words, is present() not sufficient to let the compiler know it because the test condition is "hidden" inside present()?)
Yes, that's right. The compiler needs to know at compile-time that the body of that if should be compiled only in the case that the argument not void. Putting the x.type != void check in that conditional is a reasonable solution but if you want to have a function to compute if that conditional should be evaluated, you can do so. Just mark present as a param function - which means that it returns a value that should be known at compile-time. Here is the complete example:
proc present( x ) param { return x.type != void; }
proc test( a: ?T = _void )
{
writeln();
writeln( "test| a = ", a );
writeln( "test| condition = ", a.type != void );
writeln( "test| present( a ) = ", present( a ) );
if present( a )
{
a = 10;
}
}
// no optional arg
test();
// pass an optional array
var arr: [1..5] int;
test( a = arr );
writeln();
writeln( "main| arr = ", arr );
If you would like to read more about the language design in this area, see "The Param Return Intent" subsection in "Procedures" chapter section "Return Intents" of the language specification.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With