rlang: quo, documentation, finding of 的赋值形式。或者其他的东西

rlang: The assignment form of quo, documentation, finding of. Or something

很多关于 quo 的帮助页面示例都采用这样的形式,将 quo 的输出分配给 quo:

quo <- quo(letters)
quo <- quo(toupper(!! quo))
quo
eval_tidy(quo)

很明显,这些赋值并没有像往常一样覆盖 quo 函数(因为他连续做了两次)。一流的对象,等等。

所以我对发生的事情的最佳猜测是这不是正常的赋值,而是 quo, quo<- 的赋值形式。但是我还没有得到这方面的任何信息。

效率低下:

getAnywhere(现状<-)
getAnywhere(`quo<-`)
getAnywhere(`quo <-`)
rlang:::quo<-
rlang:::`quo<-`
rlang:::`quo <-`

所以我希望有人能告诉我作业表的用途和工作原理,如果我看到的不是作业表,而是相当格言的某些方面,则更是如此” [q]uo 在自己的环境中进行自我评估。

最后,如果某处有关于此功能或用法的可访问文档,我想知道我是如何找到它的,如果没有,我可能应该告诉 Hadley。他是如何保持这么多盘子旋转而不掉下比他更多的球的,这对我来说完全是个谜。

library(rlang)

您刚刚附加了 rlang,您的搜索路径现在如下所示:

search()
#  [1] ".GlobalEnv"        "package:rlang"     "package:stats"    
#  [4] "package:graphics"  "package:grDevices" "package:utils"    
#  [7] "package:datasets"  "package:methods"   "Autoloads"        
# [10] "package:base"  

如果您在命令行以交互方式执行此操作,这应该发生在 .GlobalEnv:

quo <- quo(letters)

ls(.GlobalEnv)
# [1] "quo"

现在 quoget("quo") 开始在 .GlobalEnv 中搜索 quo,在那里找到它(您刚刚创建的 quosure)并停止:

quo
get("quo")
get("quo", .GlobalEnv)
# <quosure: global>
# ~letters

如果要查找函数,必须绕过 .GlobalEnv 并在其封闭环境 package:rlang 中开始搜索。你很幸运,这就是它所在的位置:

get("quo", as.environment("package:rlang"))
# function (expr) 
# {
#     enquo(expr)
# }
# <environment: namespace:rlang>

(哦,你看到的这个 namespace:rlang 不是我们找到 quo 的地方,而是它的封闭环境,即当它被调用时它将开始自己的搜索的地方。见世界地图:source: Suraj Gupta http://blog.obeautifulcode.com/R/How-R-Searches-And-Finds-Stuff/)

> sapply(search(), function(x) "quo" %in% ls(x))
       .GlobalEnv     package:rlang     package:stats  package:graphics 
             TRUE              TRUE             FALSE             FALSE 
package:grDevices     package:utils  package:datasets   package:methods 
            FALSE             FALSE             FALSE             FALSE 
        Autoloads      package:base 
            FALSE             FALSE 

如果您已经知道您正在寻找一个函数,您可以使用 pryr 中方便的 fget 忽略所有不是函数的东西:

pryr::fget("quo")
# function (expr) 
# {
#     enquo(expr)
# }
# <environment: namespace:rlang>

(注意:match.fun 也可以在您编写自己的函数时派上用场)。

或者你可以让R聪明点,直接用parens,R会知道它要找一个函数,这是在

中做的
quo <- quo(toupper(!! quo))

(另比较:

> bar
Error: object 'bar' not found
> bar()
Error in bar() : could not find function "bar"

错误消息暗示了 R 不能 find/looks 的东西,有和没有括号。)


现在为了好玩,让我们附上整个 tidyverse:

library(tidyverse)

搜索路径变得更加混乱:

search()
#  [1] ".GlobalEnv"        "package:forcats"   "package:stringr"  
#  [4] "package:dplyr"     "package:purrr"     "package:readr"    
#  [7] "package:tidyr"     "package:tibble"    "package:ggplot2"  
# [10] "package:tidyverse" "package:rlang"     "package:stats"    
# [13] "package:graphics"  "package:grDevices" "package:utils"    
# [16] "package:datasets"  "package:methods"   "Autoloads"        
# [19] "package:base" 

如果我们好奇并想知道在哪里可以找到 quo,我们可以使用 pryr 中的 where。同样,我们应该绕过 .GlobalEnv 并从其封闭环境 package:forcats 开始,例如:

pryr::where("quo", env = "package:forcats")
# Using environment package:forcats
# <environment: package:dplyr>
# attr(,"name")
# [1] "package:dplyr"
# attr(,"path")
# [1] "/home/aurele/R/x86_64-pc-linux-gnu-library/3.4/dplyr"

惊喜,quo 现在出现在 package:dplyr 而不是 package:rlang。这是因为 package:dplyr 在搜索路径中出现在前面,碰巧它从 rlang 重新导出 quo 以使其直接在 dplyr.[=49 中可用=]

> sapply(search(), function(x) "quo" %in% ls(x))
       .GlobalEnv   package:forcats   package:stringr     package:dplyr 
             TRUE             FALSE             FALSE              TRUE 
    package:purrr     package:readr     package:tidyr    package:tibble 
            FALSE             FALSE             FALSE             FALSE 
  package:ggplot2 package:tidyverse     package:rlang     package:stats 
            FALSE             FALSE              TRUE             FALSE 
 package:graphics package:grDevices     package:utils  package:datasets 
            FALSE             FALSE             FALSE             FALSE 
  package:methods         Autoloads      package:base 
            FALSE             FALSE             FALSE