我想完全理解C++编译器如何处理超过最大可能数的枚举,即包含-1和UINT64_MAX同时,即
enum A {
X = -1,
Y = UINT64_MAX
};
Run Code Online (Sandbox Code Playgroud)
首先,我认为编译器不接受此代码.实际上它enum被替换时不编译enum class,但上面的例子编译.根据我们对底层类型的标准:
声明一个未固定的枚举类型,其基础类型不固定(在这种情况下,基础类型是一个实现定义的整数类型,可以表示所有枚举器值;此类型不大于int,除非枚举器的值不能适合int或unsigned int.如果enumerator-list为空,则基础类型就好像枚举具有值为0的单个枚举器一样.(https://en.cppreference.com/w/cpp/language/enum)
但这对我的例子意味着什么呢?
我写了一个小样本程序来找出会发生什么:
#include <iostream>
#include <cstdint>
enum A {
X = -1,
XX = -1,
Y = UINT64_MAX
};
int main()
{
std::cout << "X unsigned: " << (uint64_t)(X) << ", signed: " << (int64_t)(X) << std::endl;
std::cout << "Y unsigned: " << (uint64_t)(Y) << ", signed: " << (int64_t)(Y) << std::endl;
std::cout << "(X …Run Code Online (Sandbox Code Playgroud) 我想创建一个包含S4类的不同变量的data.frame.对于像"POSIXlt"这样的内置类(对于日期),这很好用:
as.data.frame(list(id=c(1,2),
date=c(as.POSIXlt('2013-01-01'),as.POSIXlt('2013-01-02'))
Run Code Online (Sandbox Code Playgroud)
但是现在我有一个用户定义的类,让我们说一个名字和年龄的"Person"类:
setClass("person", representation(name="character", age="numeric"))
Run Code Online (Sandbox Code Playgroud)
但是以下失败了:
as.data.frame(list(id=c(1,2), pers=c(new("person", name="John", age=20),
new("person", name="Tom", age=30))))
Run Code Online (Sandbox Code Playgroud)
我还尝试使用人员类重载[...] - 运算符
setMethod(
f = "[",
signature="person",
definition=function(x,i,j,...,drop=TRUE){
initialize(x, name=x@name[i], age = x@age[i])
}
)
Run Code Online (Sandbox Code Playgroud)
这允许类似矢量的行为:
persons = new("person", name=c("John","Tom"), age=c(20,30))
p1 = persons[1]
Run Code Online (Sandbox Code Playgroud)
但仍然有以下失败:
as.data.frame(list(id=c(1,2), pers=persons))
Run Code Online (Sandbox Code Playgroud)
也许我必须重载更多运算符才能将用户定义的类放入数据帧中?我确信,必须有办法做到这一点,因为POSIXlt是一个S4类,它的工作原理!任何使用新R5参考类的解决方案都可以!
我不想把我的所有数据都放到人类中(你可能会问,为什么"id"不是我不使用数据帧的人的成员)!我的想法是,我的data.frame表示一个数据库中的表,其中包含许多不同类型的列,例如字符串,数字......,还有日期,间隔,地理对象等...对于我已经拥有的日期一个解决方案(POSIXlt),用于间隔,地理对象等.我可能需要指定自己的S4/R5类.
非常感谢提前.
我rhandsontable在Shiny应用程序中使用该软件包,该应用程序应具有以下功能:
actionButton(由应用程序启动时)调用以下应用程序完全符合我的要求,但我无法弄清楚如何摆脱全局变量did_recalc.这是一个最小的例子,其中数据由两个总结的数值组成.
library(shiny)
library(rhandsontable)
did_recalc <- FALSE
ui <- fluidPage(
rHandsontableOutput('table'),
textOutput('result'),
actionButton("recalc", "generate new random vals and calculate")
)
server <- function(input,output,session)({
dataset_generator <- eventReactive(input$recalc, {
df <- as.data.frame(runif(2))
output$table <- renderRHandsontable({rhandsontable(df)})
did_recalc <<- TRUE
df
}, ignoreNULL = FALSE)
output$result <- renderText({
df <- dataset_generator()
if (!is.null(input$table) && !did_recalc)
df <- hot_to_r(input$table)
did_recalc <<- FALSE
sum(df)
})
})
shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)
如果我删除!did_recalc条件output$result <- …
不幸的是,像(f+g)(3)f和g这两个都是一元函数的东西在R中不起作用.因此,我尝试以下列方式重载"+"运算符以获得一元函数:
"+.function" = function(e1, e2){
return(function(x) e1(x) + e2(x))
}
Run Code Online (Sandbox Code Playgroud)
但如果我尝试使用它,这什么都不做.代码
a = function(x) 2*x
(a+a)(2)
Run Code Online (Sandbox Code Playgroud)
产生相同的错误,如果+.function没有定义.
通过一段时间的游戏,我发现事实上有可能以这种方式添加函数:如果函数是引用类的成员函数,这是有效的!即,以下代码(连同上面的"+"定义)
clsA = setRefClass("clsA",
methods = list(
b = function(x) 2*x
))
inst_a = clsA$new()
(inst_a$b + inst_a$b)(2)
Run Code Online (Sandbox Code Playgroud)
返回"8"(如预期的那样).因此,我已经为我的问题找到了某种解决方法.现在我的问题是:
这种奇怪行为的原因是什么?为什么不+.function关心"通常"功能而是关注类成员函数?有谁知道如何将操作员"扩展"到通常的功能?
在我的代码中,我经常在不同的可迭代Qt容器类型上执行相同的操作,例如:
void removeX(QMap<qint64, QString> & map)
{
QMutableMapIterator<qint64, QString> it(map);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
void removeX(QList<QString> & list)
{
QMutableListIterator<QString> it(list);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
(我知道removeAllQList中已经有一个函数.这只是一个愚蠢的最小例子)
实际代码更复杂,因此引入了大量代码重复.我更喜欢这样的东西:
template <typename T>
void removeX_(T & container)
{
typename T::mutable_iterator it(container);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
当然,这不会编译,因为在Qt中根本没有":: mutable_iterator"类型定义.可以构建一个吗?我没有看到一个简单的方法.像"template <...> getMyMutableIterator"这样的函数在这种情况下无法工作,因为我们不允许为重载函数返回不同的类型.
但是C++ 17还有很多新的"模板魔术",我还没有真正理解.我可以想象它可能是实现上述代码的简单方法.有没有人在这里减少代码重复的解决方案?
假设我有一个x某种(未知)类型的值(特别是:标量,向量或列表).我想得到代表这个值的R表达式.如果x == 1那么这个函数应该简单地返回expression(1).对于x == c(1,2))这个函数返回expression(c(1,2)).该enquote功能是非常接近我想要的,但不完全是.
通过一些游戏,我找到了以下问题的"解决方案":
get_expr <- function(val) {
tmp_expr <- enquote(val)
tmp_expr[1] <- quote(expression())
return(eval(tmp_expr))
}
get_expr(1) # returns expression(1)
get_expr(c(1, 2)) # returns expression(c(1, 2))
get_expr(list(x = 1)) # returns expression(list(x = 1))
Run Code Online (Sandbox Code Playgroud)
但我认为我的get_expr功能是某种黑客攻击.从逻辑上讲,评估不应该是必要的.
有没有更优雅的方式来做到这一点?据我所知,对我来说substitute并不适用,因为我的get_expr函数的参数可能是评估的结果(并且substitute(eval(expr))不进行评估).
我找到了另一种方式parse(text = deparse(val)),但这更糟糕的是黑客...
我正在使用" 将鼠标悬停在ggplot上时的工具提示 "问题中的答案,将鼠标悬停功能添加到我的闪亮应用程序中的ggplot对象中.与此相反,我需要coord_fixed在ggplot中设置我的应用程序.这是一个最小的工作示例:
library(shiny)
library(ggplot2)
ui <- fluidPage(
plotOutput("plot1", height = "300px", width = "100%",
hover = hoverOpts(id = "plot_hover")),
verbatimTextOutput("hover_info")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(mtcars, aes(x=mpg,y=qsec)) + geom_point() +
coord_fixed(xlim=c(0,30),ylim=c(0,30))
})
output$hover_info <- renderPrint({
if(!is.null(input$plot_hover))
paste0(input$plot_hover$x, " ", input$plot_hover$y)
})
}
shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)
现在我的问题是我没有得到正确的x坐标.在下面的屏幕截图中,鼠标指针靠近原点,但返回的x值大约为9:
如果我调整浏览器窗口的大小,使得绘图和窗口边框之间没有空格,则坐标是正确的.在我看来,hoverOpts只是忽略了coord_fixedggplot 的布局.
设置width = "300px"而不是width = "100%"可能是一种解决方法.但这对我来说不是一个真正的选择,因为我一般需要一个可变宽度的图例,该图例位于绘图区域内.
如何获得正确的x值?