在局部变量的嵌套函数中使用“get" [英] Using 'get' Inside Nested Functions on Local Variables

查看:27
本文介绍了在局部变量的嵌套函数中使用“get"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从来没有完全理解嵌套函数和通过引用传递参数.我的策略通常是在子函数中执行诸如 get('variabletopassbyreference') 之类的操作来完成此操作.

I've never quite gotten my head around nesting functions and passing arguments by reference. My strategy is typically to do something like get('variabletopassbyreference') inside the child function to accomplish this.

到现在为止,我一直在将全局变量传递给函数,并且效果很好.今天我尝试在函数内创建局部变量,然后将它们传递给该函数内的嵌套函数,但失败了.我无法让 get 工作.我也尝试修改 posinherits 但无济于事.

Until now, I have been passing global variables to the function and this worked fine. Today I tried to create local variables inside a function and then pass those to a nested function within that function and it failed. I'm unable to get get to work. I also tried tinkering the pos and inherits but to no avail.

我在网上找不到确切的答案.如果我能让这个构造工作,那么这是我的偏好,因为我有一堆其他的函数,我已经用类似的方式编码了.如果我根本不应该做这件事而应该做其他事情,那么这些信息也将不胜感激.

I cannot find an exact answer on the net. If I could get this construct to work then that's my preference because I have a bunch of other functions that I've coded up in similar fashion. If I shouldn't be doing this at all and should be doing something else, then that information would be appreciated as well.

下面是一个例子 -

test1 <- function(a1,b1) {

  # cat(ls()) # a1 b1
  # cat(ls(pos = 1)) # c test1 test2

  testvalue <- get('c') * get(a1, inherits = TRUE) * get(b1)

  testvalue

}

test2 <- function() {

  a = 1
  b <- 2
  # cat(ls()) # a b
  test1('a','b')

}

c = 3
test2()

我收到以下错误 -

Error in get(a1, inherits = TRUE) : object 'a' not found 

更通用的例子 -

a = 0

test1 <- function(a1,b1) {

  # cat(ls()) # a1 b1
  # cat(ls(pos = 1)) # c test1 test2

  testvalue <- get('c') * a1 * b1

  assign(x = 'a', value = 2.5)
  assign(x = 'a', value = 3.5, envir = parent.frame())
  assign(x = 'a', value = 4.5, envir = .GlobalEnv)
  cat(a)
  cat(' - value of a local within test1
')
  testvalue

} 

test2 <- function() {

  a = 1
  b <- 2
  # cat(ls()) # a b

  cat(a)
  cat(' - value of a local within test2 before test1 called
')
  test1(a1 = a, b1 = b)
  cat(a)
  cat(' - value of a local within test2 after test1 called
')

}
cat(a)
cat(' - value of a global before test 2 
')
c = 3
test2()

cat(a)
cat(' - value of a global after test 2 
')

推荐答案

既然你这么问,我觉得这肯定是个糟糕的设计.推荐的方法是坚持 R 的传值方式.并且尽可能地让每个函数都将它使用的所有东西都作为参数:

Since you are asking, this definitely looks like a bad design to me. The recommended approach is to stick to R's way of pass-by-value. And as much as possible, make every function take everything it uses as arguments:

test1 <- function(a1, b1, c1 = 1) {
   testvalue <- c1 * a1 * b1   
   testvalue
}

test2 <- function(cc = 1) {
   a <- 1
   b <- 2
   test1(a1 = a, b1 = b, c1 = cc)
}

cc <- 3
test2(cc = cc)

(我将 c 替换为 cc 因为它是函数的名称,因此用作变量名是个坏主意.)

(I replaced c with cc since it is the name of a function, hence a bad idea to use as variable name.)

一种不太可接受但可能更接近您所拥有的方法是不将所有参数传递给您的函数,而让 R 在调用堆栈中查找它们:

A less acceptable but maybe closer approach to what you have is to not pass all arguments to your functions and let R look for them in the calling stack:

test1 <- function(a1, b1) {
   testvalue <- cc * a1 * b1   
   testvalue
}

test2 <- function() {
   a <- 1
   b <- 2
   test1(a, b)
}

cc <- 3
test2()

如果由于某种原因第一种方法对您不起作用,请解释原因,以便我有机会说服您.这是推荐的 R 编程方式.

If for some reason the first approach does not work for you, please explain why so I get a chance to maybe convince you otherwise. It is the recommended way of programming in R.

根据讨论和您的编辑,我建议您查看 proto 包作为 getassign 的替代方案.本质上,proto 对象是环境,因此您可以使用 base R 做任何事情,但它有助于使事情变得更清晰:

Following on the discussion and your edit, I'll recommend you look at the proto package as an alternative to get and assign. Essentially, proto objects are environments so it's nothing you can't do with base R but it helps make things a bit cleaner:

test1 <- function(x) {
   testvalue <- x$c * x$a * x$b
   x$a <- 3.5
   testvalue
}

test2 <- function(x) {
   x$a <- 1
   x$b <- 2
   cat(x$a, '
')
   test1(x)
   cat(x$a, '
')
}

library(proto)
x <- proto(c = 3)
test2(x)

从编程的角度来看,test1test2 是有副作用的函数(它们修改对象x).请注意,这是一种冒险的做法.

From a programming point of view, test1 and test2 are functions with side-effects (they modify the object x). Beware that its a risky practice.

或者更好的方法是让 test1test2 成为一个类的方法,那么如果他们修改他们正在运行的实例是可以接受的:

Or maybe a better approach is to make test1 and test2 be methods of a class, then it is acceptable if they modify the instance they are running on:

x <- proto() # defines a class

x$test1 <- function(.) {
   testvalue <- .$c * .$a * .$b
   .$a <- 3.5
   testvalue
}

x$test2 <- function(.) {
   .$a <- 1
   .$b <- 2
   cat(.$a, '
')
   .$test1()
   cat(.$a, '
')
}

library(proto)
y <- x$proto(c = 3)  # an instance of the class
y$test2()

如果您对使用第三方包 (proto) 不感兴趣,请查看 R 对构建类的支持 (setClass, setRefClass).根据您的规格,我确实相信使用面向对象的设计是正确的方法.

If you are not interested in using a third-party package (proto), then look at R's support for building classes (setClass, setRefClass). I do believe using an object-oriented design is the right approach given your specs.

这篇关于在局部变量的嵌套函数中使用“get"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆