Ошибка «*** не был объявлен в этой области»

#r #rcpp #rcpparmadillo

#r #rcpp #rcpparmadillo

Вопрос:

В этом посте я определил функцию с именем soft . Когда я использовал sourceCpp для его компиляции, сообщаемые ошибки

  • ZH не был объявлен в этой области
  • alpha0H не был объявлен в этой области
  • maxRankH не был объявлен в этой области

Я перепробовал много подходов для решения проблемы «… не был объявлен в этой области «. Однако я не нашел правильного способа или причины возникновения ошибки. Я предполагаю, что это должно быть связано с оператором if-else в функции, но не уверен.

Есть ли у вас хорошая идея для решения этой проблемы? Заранее благодарю вас!

Кстати, я не писал Rcpp ::NullableRcpp ::LogicalMatrix Ome_ = R_NilValue, Rcpp ::NullableRcpp::LogicalMatrix Ome1_ = R_NilValue, Rcpp ::NullableRcpp::LogicalMatrix Ome2_ = R_NilValue в аргументах ранее, а скорее Rcpp ::LogicalMatrix Ome, Rcpp: :Логическая матрица Ome1, Rcpp::LogicalMatrix Ome2. Но было сообщено об одной ошибке «по умолчанию отсутствует для …аргументы …», поэтому я изменил на Rcpp::NullableRcpp::LogicalMatrix …..

 #include <RcppArmadillo.h>


// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List dcSVD(arma::mat X) {
  arma::mat u, v;
  arma::vec d;
  arma::svd(u, d, v, X, "dc");
  return Rcpp::List::create(Rcpp::Named("u") = u,
                            Rcpp::Named("d") = d,
                            Rcpp::Named("v") = v);
  
}


// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
Rcpp::List soft(arma::mat X, Rcpp::Nullable<Rcpp::NumericMatrix> Z_ = R_NilValue, Rcpp::Nullable<Rcpp::LogicalMatrix> Ome_ = R_NilValue, Rcpp::Nullable<Rcpp::LogicalMatrix> Ome1_ = R_NilValue, Rcpp::Nullable<Rcpp::LogicalMatrix> Ome2_ = R_NilValue, Rcpp::Nullable<Rcpp::NumericVector> alpha0_ = R_NilValue, Rcpp::Nullable<Rcpp::NumericVector> maxRank_ = R_NilValue){
  
  
  if (Ome_.isNotNull() amp;amp; Ome1_.isNotNull() amp;amp; Ome2_.isNotNull()){
    
    Rcpp::LogicalMatrix Ome(Ome_);
    arma::umat Omega = Rcpp::as<arma::umat>(Ome);
    
    
    Rcpp::LogicalMatrix Ome1(Ome1_);
    arma::umat Omega1 = Rcpp::as<arma::umat>(Ome1);
    
    Rcpp::LogicalMatrix Ome2(Ome2_);
    arma::umat Omega2 = Rcpp::as<arma::umat>(Ome2);
    
    arma::mat X_0 = X % Omega;
    
    if (!Z_.isNotNull()){
      
      Rcpp::NumericMatrix ZH = Rcpp::wrap(X_0);
      
    }else{
      
      Rcpp::NumericMatrix ZH = Rcpp::as<Rcpp::NumericMatrix>(Z_);
    }
    
    
    if (!alpha0_.isNotNull()){
      
      Rcpp::List my_svd = dcSVD(X_0);
      arma::vec d = my_svd["d"];
      Rcpp::NumericVector alpha0H = d(1);
      
    }else{
      
      Rcpp::NumericVector alpha0H = Rcpp::as<Rcpp::NumericVector>(alpha0_);
    }
    
    if (!maxRank_.isNotNull()){
      
      Rcpp::NumericVector maxRankH = -1;
      
    }else{
      
      Rcpp::NumericVector maxRankH = Rcpp::as<Rcpp::NumericVector>(maxRank_);
    }
    
    
  }else{
    
    Rcpp::StringVector ZH = "NULL";
    Rcpp::StringVector alpha0H = "NULL";
    Rcpp::StringVector maxRankH = "NULL";
    
  }  
  
  return Rcpp::List::create(Rcpp::Named("ZH") = ZH, 
                            Rcpp::Named("alpha0H") = alpha0H, 
                            Rcpp::Named("maxRankH") = maxRankH);
  
}

  

Комментарии:

1. c следует другим правилам определения области, чем R. В частности, ZH не отображается за пределами { } того места, где он объявлен, как это было бы в R. Возможно, вы захотите переместить свои NULL объявления на один уровень выше, затем отдельные if операторы перезаписывают значения по NULL умолчанию.

2. @ArtemSokolov Спасибо! Это работает. Можете ли вы помочь объяснить другую ошибку, с которой я часто сталкиваюсь «ошибка статического утверждения: ошибка: несоответствие типа или неподдерживаемый тип» ? ? Еще раз спасибо!

3. Я не думаю, что определение области также будет работать в R. В общем, я объявляю переменные в начале вне любого условия, обычно с разумным (и различимым) значением по умолчанию, поэтому, если мои if операторы не переопределяют его, они определены и имеют что-то значимое (например, некоторую форму NA или NULL ).

4. @r2evans Попробуйте rm(y); if(TRUE) {y <- 5}; y . Несмотря y на то, что он объявлен и определен внутри if { } области, он виден за пределами этой области. Это было бы неверно в C .

5. Хорошо, я думал больше function и local , я не рассматривал if и for цикл в моем исходном заявлении. В этом смысле … R немного более разрешительный, но он не является глобальным. вздох

Ответ №1:

Правила определения области c делают так, чтобы переменные, объявленные внутри { } , не были видны за пределами этой области. Рассмотрите возможность перемещения определений по умолчанию на один уровень выше, а затем if перезаписи этих значений по умолчанию отдельными областями:

 Rcpp::List soft(...) {

    // Declare variables outside all {}
    //   to make them visible throughout the whole function
    Rcpp::NumericMatrix ZH = R_NilValue;

    // Overwrite the default values inside individual {}
    if (!Z_.isNotNull()){
      ZH = Rcpp::wrap(X_0);
    }else{
      ZH = Rcpp::as<Rcpp::NumericMatrix>(Z_);
    }

    // etc....
}