Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing a list inside a function

Tags:

list

r

I would like to do perform analysis of structure

a <- list()
replicate_letter <- function(letter) {
  return(data.frame(first_letter = rep(letter, 10),
                    second_letter = rep(letter, 10)))
}
get_letter <- function(letter) {
  if (is.null(a[[letter]])) {
    a[[letter]] <- replicate_letter(letter)
  }
  # Do further analysis, plotting,....
}

and perform it often just by calling get_letter. However, this does not work - function runs, but a is not altered.

I have figured out that this is due to attempt to change list inside the function as this

a <- list()
replicate_letter <- function(letter) {
  return(data.frame(first_letter = rep(letter, 10),
                    second_letter = rep(letter, 10)))
}
for (letter in letters[1:3]) {
  if (is.null(a[[letter]])) {
    a[[letter]] <- replicate_letter(letter)
  }
}
a

runs alright. How do I need to change function get_letter to make it work? Is it possible?

like image 919
Love-R Avatar asked Feb 02 '26 23:02

Love-R


2 Answers

The problem is that a copy of the list is modified in the function's environment, and that copy is destroyed when the function exits. R differs in this way from many other languages, in that the global environment is not (by default) modified within functions.

You should have your function return the new list:

get_letter <- function(a, letter) {
  if (is.null(a[[letter]])) {
    a[[letter]] <- replicate_letter(letter)
  }
  # Do further analysis, plotting,....

  return(a)
}

Calling:

a <- get_letter(a, 'c')
like image 64
Matthew Lundberg Avatar answered Feb 04 '26 12:02

Matthew Lundberg


I'm not quite sure if I understand your situation, so perhaps take this with a grain of salt. But be aware that you are assigning the output of a[[letter]] <- replicate_letter(letter) only within the function (which then disappears afterwards). You could try ?<<- instead. Consider:

replicate_letter <- function(letter) {
  return(data.frame(first_letter = rep(letter, 10),
                    second_letter = rep(letter, 10)))
}
get_letter <- function(letter) {
  if (is.null(a[[letter]])) {
    a[[letter]] <<- replicate_letter(letter)
  }
  # Do further analysis, plotting,....
}
get_letter("a")
a
# $a
#    first_letter second_letter
# 1             a             a
# 2             a             a
# 3             a             a
# 4             a             a
# 5             a             a
# 6             a             a
# 7             a             a
# 8             a             a
# 9             a             a
# 10            a             a

The help for <<- reads (in part):

The operators <- and = assign into the environment in which they are evaluated. The operator <- can be used anywhere, whereas the operator = is only allowed at the top level (e.g., in the complete expression typed at the command prompt) or as one of the subexpressions in a braced list of expressions.

The operators <<- and ->> are normally only used in functions, and cause a search to be made through parent environments for an existing definition of the variable being assigned. If such a variable is found (and its binding is not locked) then its value is redefined, otherwise assignment takes place in the global environment. Note that their semantics differ from that in the S language, but are useful in conjunction with the scoping rules of R. See ‘The R Language Definition’ manual for further details and examples.

(The boldface is mine.)

like image 31
gung - Reinstate Monica Avatar answered Feb 04 '26 12:02

gung - Reinstate Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!