Тестовая функция для проверки необязательного аргумента

В связи с моим предыдущим вопросом я попытался сделать функция present() для проверки наличия необязательного аргумента. Однако следующий код

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 );

выдает ошибку времени компиляции

mytest.chpl:3: In function 'test':
mytest.chpl:13: error: illegal lvalue in assignment
mytest.chpl:13: error: a void variable cannot be assigned

в котором говорится, что строка a = 10; проблематична. С другой стороны, если я использую строку 2 вместо строки 1, код работает так, как ожидалось:

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 

Кроме того, если я заменю строку 1 или 2 на if isArray( a ), код также сработает. Означает ли это, что нам нужно явно сообщить компилятору, что строка a = 10; не достигается, когда a равно _void? (Другими словами, разве present() недостаточно, чтобы сообщить об этом компилятору, потому что тестовое условие «спрятано» внутри present()?)


person roygvib    schedule 15.12.2018    source источник


Ответы (1)


Означает ли это, что нам нужно явно сообщить компилятору, что строка a = 10; не достигается, когда _void? (Другими словами, present() недостаточно, чтобы компилятор знал об этом, потому что тестовое условие «скрыто» внутри present()?)

Да все верно. Компилятор должен знать во время компиляции, что тело этого if должно быть скомпилировано только в том случае, если аргумент не пуст. Включение проверки x.type != void в это условие является разумным решением, но если вы хотите иметь функцию для вычисления, если это условие должно быть оценено, вы можете сделать это. Просто отметьте present как функцию param, что означает, что она возвращает значение, которое должно быть известно во время компиляции. Вот полный пример:

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 );

Если вы хотите узнать больше о дизайне языка в этой области, см. "The Param Return Intent" в разделе "Procedures" главы "Return Intent" документа спецификация языка.

person mppf    schedule 17.12.2018
comment
Я видел много param в различных кодах Chapel (на Github), но я, наконец, понял, почему это важно для такого рода использования... (до сих пор мое использование param похоже на parameter в Фортране (просто для определения параметр времени компиляции). Я прочитаю спецификацию PDF для более подробной информации. Большое спасибо :) - person roygvib; 18.12.2018