R 让两个函数访问单个函数的正确方法';什么是环境?

R 让两个函数访问单个函数的正确方法';什么是环境?,r,scope,R,Scope,根据中提供的答案,我设置了一对函数,它们都访问同一个子函数的环境。这个例子是可行的,但我想看看我是否错过了将两个顶级函数“连接”到内部环境的更干净的方法 (背景故事:我想写一对互补函数,它们共享一个变量,例如本例中的“count”和满足不允许函数修改全局环境的CRAN包要求。) 您可以去掉工厂函数,更明确地使用环境。这样的解决方案也会奏效 .env<-(function() { count <- 0 f <- function(x) { cou

根据中提供的答案,我设置了一对函数,它们都访问同一个子函数的环境。这个例子是可行的,但我想看看我是否错过了将两个顶级函数“连接”到内部环境的更干净的方法

(背景故事:我想写一对互补函数,它们共享一个变量,例如本例中的“count”满足不允许函数修改全局环境的CRAN包要求。)


您可以去掉工厂函数,更明确地使用环境。这样的解决方案也会奏效

.env<-(function() {
    count <- 0
    f <- function(x)  {
        count <<- count + 1
        return( list(mean=mean(x), count=count))
    }   
    return(environment())
})()



statfoo <- function(x){
    list(.env$f(x),plus=2)
}
statbar <- function(x){
    list(.env$f(x),minus=3)
}

.env您可以像这样使用引用类:

foobar <- setRefClass(
    'foobar',
    fields = list(count='numeric'),
    methods = list(
        initialize=function() {
            .self$initFields(count = 0L)
        },
        statfoo = function(x) {
            count <<- count + 1L
            list(list(mean=mean(x), count=count), plus=2)
        },
        statbar = function(x){
            count <<- count + 1L
            list(list(mean=mean(x), count=count), minus=3)
        }
    )
)()

foobar$statfoo(5)
foobar$statbar(3)

foobar更干净的方法是使用面向对象的方法。使用参考类已经有了答案

使用类的典型面向对象方法将创建一个类,然后创建一个单例对象,即该类的单个对象。当然,创建一个类只是从中创建一个对象有点浪费,所以这里我们提供一个原型示例。(创建一个函数来封装
count
,而实际工作的函数也有类似的问题——创建一个封装函数只是为了运行它一次。)原型允许直接创建对象,而不需要创建一个类来只使用它一次。这里的
foobar
是具有属性
count
和方法
stats
statfoo
statbar
的原型对象。请注意,我们计算了
stats
,以避免在
statfoo
statbar
中重复其代码。(继续向下)

第二种设计是将
statfoo
statbar
作为独立功能,并且只在
foobar
中保留
count
stats
(继续往下)


另一个简单的选择是创建一个环境并将其分配给这两个函数。在这里,我使用更简单的函数进行说明,但这很容易扩展:

f1 <- function() {count <<- count + 1; return(paste("hello", count))}
f2 <- function() {count <<- count + 1; return(paste("goodbye", count))}

environment(f1) <- environment(f2) <- list2env(list(count=0))

两个函数都有相同的环境。

我认为所有发布的答案都很好。我选择Flick是因为它不需要额外的包(
proto
),也不需要
func$part
构造或配置命令(
环境(f1)
foobar <- setRefClass(
    'foobar',
    fields = list(count='numeric'),
    methods = list(
        initialize=function() {
            .self$initFields(count = 0L)
        },
        statfoo = function(x) {
            count <<- count + 1L
            list(list(mean=mean(x), count=count), plus=2)
        },
        statbar = function(x){
            count <<- count + 1L
            list(list(mean=mean(x), count=count), minus=3)
        }
    )
)()

foobar$statfoo(5)
foobar$statbar(3)
library(proto)

foobar <- proto(count = 0, 
          stats = function(., x) {
               .$count <- .$count + 1
               list(mean = mean(x), count = .$count)
          },
          statfoo = function(., x) c(.$stats(x), plus = 2),
          statbar = function(., x) c(.$stats(x), plus = 3)
)

foobar$statfoo(1:3)
foobar$statbar(2:4)
> foobar$statfoo(1:3)
$mean
[1] 2

$count
[1] 1

$plus
[1] 2

> foobar$statbar(2:4)
$mean
[1] 3

$count
[1] 2

$plus
[1] 3
library(proto)

foobar <- proto(count = 0, 
          stats = function(., x) {
               .$count <- .$count + 1
               list(mean = mean(x), count = .$count)
          }
)

statfoo <- function(x) c(foobar$stats(x), plus = 2)
statbar <- function(x) c(foobar$stats(x), plus = 3)

statfoo(1:3)
statbar(2:4)
foobar <- local({
            count <- 0
            function(x) {
               count <<- count + 1
               list(mean = mean(x), count = count)
            }
          })

statfoo <- function(x) c(foobar(x), plus = 2)
statbar <- function(x) c(foobar(x), plus = 3)

statfoo(1:3)
statbar(2:4)
f1 <- function() {count <<- count + 1; return(paste("hello", count))}
f2 <- function() {count <<- count + 1; return(paste("goodbye", count))}

environment(f1) <- environment(f2) <- list2env(list(count=0))
> f1()
[1] "hello 1"
> f2()
[1] "goodbye 2"
> f1()
[1] "hello 3"