我是一个相对绿色的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
Run Code Online (Sandbox Code Playgroud)
为什么会这样,以及如何使用相同的极端情况和基本功能"相同"的持久性来测试身份?我找不到任何Rcpp糖用于此目的,但是如果我找不到直接解决方案,我怀疑无序集或者可能使用唯一函数来测试身份.
如果我的C++是非惯用的/危险的,我也会感激反馈,如果我一直含糊不清,请在下面留言,我会修改我的问题.
谢谢
呵呵,看来你无意中发现了一个小错误-我们不转换bool到LogicalVector以预期的方式.
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
LogicalVector return_true() {
return true;
}
/*** R
return_true()
*/
Run Code Online (Sandbox Code Playgroud)
给
> return_true()
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
那么也许LogicalVector::create(true)现在回来?
代码中的另一个大问题:identical返回a SEXP,而不是bool!您希望bool明确地获得结果:
Shield<SEXP> result(identical(val, elem));
if (LOGICAL(result)[0]) { ... }
Run Code Online (Sandbox Code Playgroud)
虽然直接分配结果bool应该可行,但似乎可能没有.回电话时还有像这样的陷阱.
也就是说,对您的代码的其他评论:
SEXP除非你知道自己在做什么,否则不要使用原始产品.在这里你很幸运,因为Lists的孩子被隐含地保护,但一般来说这是不安全的.i,这是最常见的格式(看起来很奇怪ith).事实证明,还有一个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);
Run Code Online (Sandbox Code Playgroud)
所以你可能只想用它.