在Rcpp中测试价值身份

时间:2014-09-14 00:49:41

标签: r rcpp

我是一个相对绿色的Rcpp用户,我不确定如何测试两个值是否相同。

例如,以下函数用于测试列表中是否包含值,但是对于简单测试用例返回的结果不正确

#include <Rcpp.h>
using namespace Rcpp;    

// [[Rcpp::export]]
LogicalVector is_member (SEXP val, List coll) {    

    int coll_len = coll.size();    

    if (coll_len == 0) {
        return LogicalVector::create();
    } else {    

        Function identical("identical");    

        for (int ith = 0; ith < coll_len; ++ith) {    

            SEXP elem = coll[ith];    

            if (identical(val, elem)) {
                return true;
            }
        }    

        return false;
    }
}

is_member(1L, list(1L))
# FALSE
is_member(NaN, list(NaN, NaN))
# False

为什么会这样,以及如何使用相同的极端情况和基本功能“相同”的持久性来测试身份?我找不到任何Rcpp糖用于此目的,但是如果我找不到直接解决方案,我怀疑无序集或者可能使用唯一函数来测试身份。

如果我的C ++是非惯用的/危险的,我也会感激反馈,如果我一直含糊不清,请在下面留言,我会修改我的问题。

由于

1 个答案:

答案 0 :(得分:5)

嗯,看起来你偶然发现了一个小小的错误 - 我们没有按照预期的方式将bool转换为LogicalVector

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
LogicalVector return_true() {
  return true;
}

/*** R
return_true()
*/

给出

> return_true()
[1] FALSE

所以也许现在只返回LogicalVector::create(true)

代码中的另一个重大问题:identical会返回SEXP,而不是bool!您希望明确地将结果作为bool

Shield<SEXP> result(identical(val, elem));
if (LOGICAL(result)[0]) { ... }

虽然直接将结果分配给bool应该有效,但似乎它可能没有。当回到R时,仍有这样的陷阱。

那就是对你的代码的其他评论:

  1. 一般来说,回拨R很慢*,所以除非必须,否则不要这样做,
  2. 除非您知道自己在做什么,否则不要使用原始SEXP。在这里你很幸运,因为List的孩子受到了隐性保护,但总的来说这是不安全的。
  3. 只需调用迭代器索引i,这是最常见的格式(看到ith会觉得奇怪)。
  4. 事实证明,identical也有一个C API。在RInternals.h,我们有

    /* R_compute_identical:  C version of identical() function
       The third arg to R_compute_identical() consists of bitmapped flags for non-default options:
       currently all default to TRUE, so the flag is set for FALSE values:
       1 = !NUM_EQ
       2 = !SINGLE_NA
       4 = !ATTR_AS_SET
       8 = !IGNORE_BYTECODE
    */
    Rboolean R_compute_identical(SEXP, SEXP, int);
    

    因此您可能只想使用它。

相关问题