Note that there are some explanatory texts on larger screens.

plurals
  1. POIs it possible to modify an object on a list in a parent frame in R?
    primarykey
    data
    text
    <p>I'm working on an R package that has a number of functions that follow a non-R-standard practice of modifying in place the object passed in as an argument. This normally works OK, but fails when the object to be modified is on a list. </p> <p>An function to give an example of the form of the assignments:</p> <pre><code>myFun&lt;-function(x){ xn &lt;- deparse(substitute(x)) ev &lt;- parent.frame() # would do real stuff here .. # instead set simple value to modify local copy x[[1]]&lt;-"b" # assign in parent frame if (exists(xn, envir = ev)) on.exit(assign(xn, x, pos = ev)) # return invisibly invisible(x) } </code></pre> <p>This works:</p> <pre><code>&gt; myObj &lt;-list("a") &gt; myFun(myObj) &gt; myObj [[1]] [1] "b" </code></pre> <p>But it does not work if the object is a member of a list:</p> <pre><code>&gt; myObj &lt;-list("a") &gt; myList&lt;-list(myObj,myObj) &gt; myFun(myList[[1]]) &gt; myList [[1]] [[1]][[1]] [1] "a" [[2]] [[2]][[1]] [1] "a" </code></pre> <p>After reading answers to other questions here, I see the docs for <code>assign</code> clearly state:</p> <p><code>assign does not dispatch assignment methods, so it cannot be used to set elements of vectors, names, attributes, etc.</code></p> <p>Since there is an existing codebase using these functions, we cannot abandon the modify-in-place syntax. Does anyone have suggestions for workarounds or alternative approaches for modifying objects which are members of a list in a parent frame?</p> <p>UPDATE:</p> <p>I've considered trying to roll my own assignment function, something like:</p> <pre><code>assignToListInEnv&lt;-function(name,env,value){ # assume name is something like "myList[[1]]" #check for brackets index&lt;-regexpr('[[',name,fixed=TRUE)[1] if(index&gt;0){ lname&lt;-substr(name,0,index-1) #check that it exists if (exists(lname,where=env)){ target&lt;-get(lname,pos=env) # make sure it is a list if (is.list(target)){ eval(parse(text=paste('target',substr(name,index,999),'&lt;-value',sep=''))) assign(lname, target, pos = env) } else { stop('object ',lname,' is not a list in environment ',env) } } else { stop('unable to locate object ',lname,' in frame ',env) } } } </code></pre> <p>But it seems horrible brittle, would need to handle many more cases (<code>$</code> and <code>[</code> as well as <code>[[</code>) and would probably still fail for <code>[[x]]</code> because <code>x</code> would be evaluated in the wrong frame... </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload