为 Rcpp 打印泛型 class
print generic for Rcpp class
我在为 Rcpp class 编写 R
通用打印机时遇到一些问题。想想 http://dirk.eddelbuettel.com/code/rcpp/Rcpp-modules.pdf 第 8 页的 Uniform 示例。我试过像这样定义一个泛型:
# Create new Uniform object:
uniform = Uniform$new(1, 2)
class(uniform)
## [1] "Rcpp_Uniform"
## attr(,"package")
## [1] "uniform"
# Printer for the object:
print.Rcpp_Uniform = function (x, ...) { message("Hi, I am an uniform object") }
现在,如果我只输入 uniform
,我会得到:
C++ object <000000000d825c80> of class 'Uniform' <000000000287b090>
但这是我尽量避免的。直接调用打印机给出了我喜欢的东西:
print(uniform)
## Hi, I am an uniform object
有没有办法不调用打印函数直接使用自定义打印机?
感谢 Dirks 的提示,我有了一个解决方案。这是包含统一 class(Dirks Rcpp Modules 文档的副本)和 Rcpp 模块定义的 cpp 文件 uniform.cpp
:
// BEGIN uniform.cpp
#include <Rcpp.h>
using namespace Rcpp;
class Uniform {
public:
Uniform(double min_, double max_) : min(min_), max(max_) {}
NumericVector draw(int n) const {
RNGScope scope;
return runif( n, min, max );
}
double min, max;
};
double uniformRange( Uniform* w) {
return w->max - w->min;
}
RCPP_MODULE(unif_module) {
class_<Uniform>( "Uniform" )
.constructor<double,double>()
.field( "min", &Uniform::min )
.field( "max", &Uniform::max )
.method( "draw", &Uniform::draw )
.method( "range", &uniformRange )
;
}
// END uniform.cpp
现在可以获取和使用:
library(Rcpp)
## Warning: package 'Rcpp' was built under R version 3.4.3
sourceCpp(file = "uniform.cpp")
uniform = Uniform$new(0, 10)
# Default printer:
uniform
## C++ object <00000000137a2e90> of class 'Uniform' <0000000015256dc0>
class(uniform)
## [1] "Rcpp_Uniform"
## attr(,"package")
## [1] ".GlobalEnv"
现在的线索是将方法 show
定义为 S4 class Rcpp_Uniform
的自定义打印机。之后打印机执行所需的操作:
setMethod("show", class(uniform), function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
## [1] "show"
uniform
##
## Hi, I am an uniform object!
##
## I was initialized with a minimum value of 0
## and a maximum value of 10.
##
## Therefore my range is 10.
在包中使用
要在将 C++
class 公开到 R
之后将该打印机设置为默认打印机,只需创建一个 R
文件(例如 R/uniform_printer.R
) 并将以下代码放在那里:
setMethod("show", "Rcpp_Uniform", function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
请注意,有必要通过字符串明确引用 class(此处为 Rcpp_Uniform
)。
这里的一个缺点是,这会在构建包时发出警告,因为在构建包时没有 class 的定义。如果在获取 cpp 文件之前从上方运行 setMethod
函数,则会出现相同的警告。
避免此警告的方法是在 setMethod
前面设置一个 class。这看起来像这样:
setClass("Rcpp_Uniform")
setMethod("show", "Rcpp_Uniform", function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
老实说,我不知道这有多合适。但它在一个包中工作正常。
我在为 Rcpp class 编写 R
通用打印机时遇到一些问题。想想 http://dirk.eddelbuettel.com/code/rcpp/Rcpp-modules.pdf 第 8 页的 Uniform 示例。我试过像这样定义一个泛型:
# Create new Uniform object:
uniform = Uniform$new(1, 2)
class(uniform)
## [1] "Rcpp_Uniform"
## attr(,"package")
## [1] "uniform"
# Printer for the object:
print.Rcpp_Uniform = function (x, ...) { message("Hi, I am an uniform object") }
现在,如果我只输入 uniform
,我会得到:
C++ object <000000000d825c80> of class 'Uniform' <000000000287b090>
但这是我尽量避免的。直接调用打印机给出了我喜欢的东西:
print(uniform)
## Hi, I am an uniform object
有没有办法不调用打印函数直接使用自定义打印机?
感谢 Dirks 的提示,我有了一个解决方案。这是包含统一 class(Dirks Rcpp Modules 文档的副本)和 Rcpp 模块定义的 cpp 文件 uniform.cpp
:
// BEGIN uniform.cpp
#include <Rcpp.h>
using namespace Rcpp;
class Uniform {
public:
Uniform(double min_, double max_) : min(min_), max(max_) {}
NumericVector draw(int n) const {
RNGScope scope;
return runif( n, min, max );
}
double min, max;
};
double uniformRange( Uniform* w) {
return w->max - w->min;
}
RCPP_MODULE(unif_module) {
class_<Uniform>( "Uniform" )
.constructor<double,double>()
.field( "min", &Uniform::min )
.field( "max", &Uniform::max )
.method( "draw", &Uniform::draw )
.method( "range", &uniformRange )
;
}
// END uniform.cpp
现在可以获取和使用:
library(Rcpp)
## Warning: package 'Rcpp' was built under R version 3.4.3
sourceCpp(file = "uniform.cpp")
uniform = Uniform$new(0, 10)
# Default printer:
uniform
## C++ object <00000000137a2e90> of class 'Uniform' <0000000015256dc0>
class(uniform)
## [1] "Rcpp_Uniform"
## attr(,"package")
## [1] ".GlobalEnv"
现在的线索是将方法 show
定义为 S4 class Rcpp_Uniform
的自定义打印机。之后打印机执行所需的操作:
setMethod("show", class(uniform), function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
## [1] "show"
uniform
##
## Hi, I am an uniform object!
##
## I was initialized with a minimum value of 0
## and a maximum value of 10.
##
## Therefore my range is 10.
在包中使用
要在将 C++
class 公开到 R
之后将该打印机设置为默认打印机,只需创建一个 R
文件(例如 R/uniform_printer.R
) 并将以下代码放在那里:
setMethod("show", "Rcpp_Uniform", function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
请注意,有必要通过字符串明确引用 class(此处为 Rcpp_Uniform
)。
这里的一个缺点是,这会在构建包时发出警告,因为在构建包时没有 class 的定义。如果在获取 cpp 文件之前从上方运行 setMethod
函数,则会出现相同的警告。
避免此警告的方法是在 setMethod
前面设置一个 class。这看起来像这样:
setClass("Rcpp_Uniform")
setMethod("show", "Rcpp_Uniform", function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
老实说,我不知道这有多合适。但它在一个包中工作正常。