简体   繁体   English

R:在范围界定中,将参数传递给内部函数,以及

[英]R: On scoping, passing arguments to interior functions, and

The example below is another instance of my ongoing quest to be better at predicting what R will do. 下面的示例是我正在进行的寻求更好地预测R会做什么的另一个实例。 Despite having read the material on matching and scoping any number of times, I continue to have difficulty in passing variables, and it seems clear that there are either additional rules I am missing, or I am misunderstanding some of the rules I have, supposedly, learned. 尽管已经阅读了很多次关于匹配和作用域的材料,但我仍然难以传递变量,而且显然我可能遗漏了其他规则,或者我误解了我所拥有的某些规则,学到了。

Here ff() calls gg() four times. 此处ff()调用gg()四次。 The output of these calls is below. 这些调用的输出如下。 Here instance 1 and 2 confirm my expectations. 在这里实例1和实例2证实了我的期望。 They find aa in the execution environment of ff , and cc in the enclosing environment of the function definition of gg . 他们在ff的执行环境中找到aa ,在gg的函数定义的封闭环境中找到cc But instances 2 and 3 surprised me. 但是实例2和实例3让我感到惊讶。 For 3, I was not sure what would happen, as I am still a little foggy on whether a variable passed via ... retains its name. 对于3,我不确定会发生什么,因为我对通过...传递的变量是否保留其名称还有些不确定。 If not, I figured the garbage collector might get it. 如果没有,我认为垃圾收集器可能会得到它。 But I really expected 4 to pass a variable called cc with the value 13 into the function, and it does not. 但是我确实希望4将一个名为cc的值13传递给函数,但事实并非如此。

My original version of gg() did not have the ls() the list2env() in it. 我的原始gg()版本没有ls() list2env() When I added the ls() , it seemed to show that the ... passed a ... object, with the cc inaccessible inside it to the scope of the cc in the function body. 当我加入ls()它似乎表明, ...传递一个...对象,与cc内它不能访问在函数体的cc的范围。 Note that the ls() did not show the ... until I added the all.names=TRUE. 请注意,在我添加all.names = TRUE之前,ls()不会显示... I then added the list2env(), conditional on there being something in the ... . 然后,我添加了list2env(),条件是在...存在某些内容。 but as best I can tell, this does nothing at all. 但据我所知,这根本没有任何作用。

So, three questions: 因此,三个问题:

  1. What is up with list2env? list2env的问题是什么? Why does it have no effect here? 为什么这里没有效果?
  2. How does one make named arguments (in the sense of an argument assigned a name by tag) in a ... generally available inside the function as if the name had been a formal? 如何在函数内部通常可以使用的...中使命名实参(即通过标签分配了名称的实参),就好像名称是正式的一样?
  3. Same question as (2), but with respect to a variable that has a name, or is a name, without that name being assigned via tag in the argument list. 与(2)相同的问题,但是关于具有名称或名称的变量,而没有通过参数列表中的标记分配该名称。

aa <- 2
bb <- 3
cc <- 11
gg <- function(X, ...){
  if(length(alist(...)) > 1){list2env(alist(...), envir = parent.frame())} 
  env_vars <- ls(all.names=TRUE)
  out <-  cc * X
  print(env_vars)
  cat(X, ",  out = ", out, "\n", sep="")
}

ff <- function(){
  aa <- 5
  bb <- 7
  cc <- 13

  gg(aa)        \# 1
  gg(X=aa)      \# 2
  gg(aa, cc)    \# 3
  gg(aa, cc=cc) \# 4
}

ff()

[1] "..." "X"  
5,  out = 55
[1] "..." "X"  
5,  out = 55
[1] "..." "X"  
5,  out = 55
[1] "..." "X"  
5,  out = 55

A big thank you! 十分感谢你! to whoever fixed my formatting. 给固定我格式的人。

This does seem strange but with some trial and error we find that 这看起来确实很奇怪,但是经过反复试验,我们发现

L <- list(...)
list2env(L, environment())

will inject the ... variables into the current environment if the actual arguments are named. 如果已命名实际参数,则会将...变量注入当前环境。 It seems that it is important to create an intermediate variable to hold the list, here L . 似乎重要的是创建一个中间变量来保存列表,此处为L

In general one could use with like this if the actual arguments are named: 通常with如果实际的参数被命名为:

g <- function(X, ...) with(list(...), {
   print(ls())
})
g(1, cc = 2)
## [1] "cc"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM