перезаписать переменную в родительской функции из внутренней функции, не создавая переменную вне родительской функции - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь перезаписать переменную a в 'external_func' значением из 'inner_func'.Я не хочу, чтобы он генерировал переменную вне функции 'outer_func'.

inner_func <- function(){
  a <<- 30
}

outer_func <- function(){
  a <- 10
  inner_func()
  print(a)
}

outer_func()

Вывод равен 10, но он должен быть 30.

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Вот 3 варианта.(1) не вносит изменений в inner_func и (3) не вносит изменений в outer_func.

1) копирует и сбрасывает среду inner_func Создает копию inner_func вouter_func и приведите текущую среду к копии.В inner_func не вносятся изменения, и к outer_func добавляется только одна строка, которая создает копию и изменяет ее среду.

outer_func <- function() {
  a <- 10
  environment(inner_func) <- environment() 
  inner_func()
  print(a)
}

outer_func()
## [1] 30

2) гнездо inner_func в outer_func Еще один способ сделать это - вложить inner_func в outer_func.

outer_func <- function() {

  inner_func <- function() {
    a <<- 30
  }

  a <- 10
  inner_func()
  print(a)
}

outer_func()
## [1] 30

3) передать окружение через arg Другой способ - передать окружение, в котором a, расположено inner_func через аргумент.Делая родительский фрейм значением по умолчанию для этого аргумента, мы можем избежать внесения каких-либо изменений в outer_func.

inner_func <- function(envir = parent.frame()) {
  envir$a <- 30
}

outer_func <- function() {
  a <- 10
  inner_func()
  print(a)
}

outer_func()
## [1] 30

Примечание

Любое из них может быть расширено для установки конкретной матрицыэлементы, если a определен, скажем, как это в outer_func.

a <- matrix(1:4, 2)

В (1) и (2) измените inner_func для использования, например:

a[1,1] <<- 30

и в (3) используйте, например, это в inner_func:

envir$a[1,1] <- 30
0 голосов
/ 04 октября 2018

Другие ответы сосредоточены на том, как заставить outer_func и inner_func вести себя так, как вы ожидаете, что они будут вести себя.Я постараюсь показать , почему они этого не делают.

Если вы переопределите inner_func для печати его родительской среды, вы увидите, что это не среда вызывающего, а глобальная среда.

inner_func <- function(){
  print(parent.env(environment()))
  a <<- 30
}

Теперь вызовите outer_func и посмотритечто он пытается найти переменную a в этой среде, а не в среде outer_func.

outer_func()
#<environment: R_GlobalEnv>
#[1] 10

И когда вы печатаете a, после вызова outer_func он имеет ожидаемыйзначение.

a
#[1] 30

Функция inner_func не нашла a, поэтому создала ее в GlobalEnv.

Сравните вышеприведенное со следующим.A inner_func определяется в outer_func.Теперь присваивание <<- находит a и меняет его значение.

outer_func2 <- function(){
  inner_func <- function(){
    print(parent.env(environment()))
    a <<- 30
  }

  a <- 10
  inner_func()
  print(a)
}

rm(a)
outer_func2()
#<environment: 0xdd06e18>
#[1] 30

Но поскольку outer_func2 не присваивает свое значение, a не существует в GlobalEnv.Он был изменен только в outer_func, единственном месте, где он существует.

a
#Error: object 'a' not found
0 голосов
/ 04 октября 2018

Вы можете использовать assign с parent.frame() (parent.frame() s окружение внешней функции, parent.frame(2) будет глобальной средой в этом случае):

inner_func <- function(){
  assign("a", 30, envir = parent.frame())
}

outer_func <- function(){
  a <- 10
  inner_func()
  print(a)
}

outer_func()

Однако будьте осторожныпотому что использование таких побочных эффектов, как, делает код намного более сложным и обычно нецелесообразным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...