功能范围:使用低级功能中的高级功能结果

时间:2018-03-04 19:50:27

标签: r function scope

我想在低级(内部)函数high_lvl_fun中使用来自高级(外部)函数low_lvl_fun的计算。低级函数是高级函数的参数(我想使用具有不同参数集的不同函数)。我可重复的例子:

set.seed(101)

low_lvl_fun <- function(x, y){ # low-level (inner) function
  sum((x-y)^2) # Mean Squared Error
}

high_lvl_fun <- function(x, y = NULL, FUN, args){ # high level (outer) function

# Just some toy changes in y to check if the code works
  if(length(y) == 0){
    y <- rep(1, length(x))
  }else{
    y <- rep(2, length(x))
  }

  do.call(FUN, args = args) # Call of low_lvl_fun
}

低级功能计算均方误差。高级函数对向量y执行一些操作并调用低级函数。声明这样的论证和高级函数调用:

x <- rnorm(100)
high_lvl_fun(x, y = NULL, FUN = "low_lvl_fun", args = list(x, y))

导致了这样的错误:

  

do.call出错(FUN,args = args):找不到对象'y'

我理解低级函数假定y的值是NULL(如在高级函数调用中声明的那样),但是,我不知道如何更改范围其中低级函数搜索y

我想出的唯一解决方案是在全球环境中声明y

high_lvl_fun2 <- function(x, y = NULL, FUN, args){ # high level (outer) function

  if(length(y) == 0){
    y <<- rep(1, length(x))
  }else{
    y <<- rep(2, length(x))
  }

  do.call(FUN, args = args) # Call of low_lvl_fun
}

但是,我想避免在全局环境中修改y

编辑:(更多细节)

低级别功能可以使用xy以外的参数。它可能还只需要x和其他参数,而不是y,例如:

low_lvl_fun2 <- function(x){sd(x)/mean(x)}

另一个重要的事情是高级和低级函数可以使用相同名称的参数(如上所述,其中两个函数都有名为xy的参数)并且它会很好没有被迫重写低级功能。不幸的是,@ Andrea建议的注释中的实现不符合这个条件,因为匹配两个具有相同名称的参数会引发错误:

high_lvl_fun <- function(x, y = NULL, FUN, ...){ # Function suggested by @Andrea

  dots <- lazy_eval(lazy_dots(...))

  # Just some toy changes in y to check if the code works
  if(length(y) == 0){
    y <- rep(1, length(x))
  }else{
    y <- rep(2, length(x))
  }

  args <- c(list(x , y) , dots)

  do.call(FUN, args = args) # Call of low_lvl_fun
}

# Calling the low-level function at the beginning of the post
high_lvl_fun(x = 1:10, y = 2:11, FUN = "low_lvl_fun", x = x, y = y)
  

high_lvl_fun出错(x = 1:10,y = 2:11,FUN =“low_lvl_fun”,x = x,   :形式参数“x”由多个实际参数匹配

2 个答案:

答案 0 :(得分:0)

假设low_lvl_fun()仅使用xy。这应该做的工作

high_lvl_fun <- function(x, y = NULL, FUN ){ # high level (outer) function

  # Just some toy changes in y to check if the code works
  if(length(y) == 0){
    y <- rep(1, length(x))
  }else{
    y <- rep(2, length(x))
  }

  args <- list(x = x, y = y)


  do.call(FUN, args = args) # Call of low_lvl_fun
}

答案 1 :(得分:0)

作为一个更普遍的解决方案,我建议 使用...参数

require(lazyeval)

high_lvl_fun <- function(x, y = NULL, FUN, ...){ # high level (outer) function

  dots <- lazy_eval(lazy_dots(...))

  # Just some toy changes in y to check if the code works
  y <- y+1

  args <- c(list(x , y) , dots)

  do.call(FUN, args = args) # Call of low_lvl_fun
}

# Ex 1
f <- function(x, y , z) {x+y+z}
high_lvl_fun (x = 1, y = 2,  FUN = f, z = 3) 

# Ex 2
g <- function(x, y , z, mean , sd) {
  n <- x+y+z
  sum(rnorm(n , mean , sd))

}
high_lvl_fun (x = 1, y = 2,  FUN = g, z = 3, mean = 100, sd = 1)