title: How to `list2env()` (or pipe into `assign()`) within a function call?
body: <p>I have a use-case for mapping a function to a vector and then assigning the results to individual objects in the parent environment - not the global environment, but the environment that the <code>map()</code> was called from. Specifically, this is all happening within a function, so I want to assign these objects to the function's environment for subsequent use within the function call, and only there.</p>
  <p>I understand that you can specify environments either by ascending numeric position, with the global as 1, or by counting back from the current environment, namely using <code>rlang::caller_env()</code>. By either method, though, I have no reliable method of specifying the desired function execution environment in cases like this. As the below reprex shows, I can get it working in one specific case with <code>rlang::caller_env(6)</code>, but it's obvious that counting exactly 6 frames back happens to work in this one case, with its specific pipe chain and sequence of operations, and any situation could have any other needed value there - I only found that 6 was the right number here by printing the traceback within the function. When using <code>map()</code>, it's 13 or something, probably because of all the nested function calls within <code>map()</code>. And I can't get it working at all with <code>list2env()</code></p>
  <p>So what I'm looking for is some argument I can provide to either <code>list2env()</code> or <code>assign()</code> that will clearly and consistently cause the assignment to occur specifically in the environment of the function that I'm using them within, even if I call those functions at the end of a pipe chain.</p>
  <pre class="lang-r prettyprint-override"><code>
  library(tidyverse)
  library(rlang, warn.conflicts = FALSE)
  
  ## Trying to assign the value 'foo' to an object named 'bar' in a specific
  ## location
  
  # Fails because `bar` is assigned in the pipe execution evironment
  'foo' %&gt;% assign(x = 'bar')
  exists('bar')
  #&gt; [1] FALSE
  
  # Works because `pos = 1` refers specifically to the global environment
  'foo' %&gt;% assign(x = 'bar', pos = 1)
  exists('bar')
  #&gt; [1] TRUE
  rm(bar)
  
  # Works because assign isn't in a pipe, and its special, default `pos` of
  # `-1` refers to the function execution environment, as desired
  exec(function() {
    assign('bar', 'foo')
    exists('bar', inherits = FALSE)
  })
  #&gt; [1] TRUE
  rm(bar)
  #&gt; Warning in rm(bar): object 'bar' not found
  
  # Fails because the function's exec. env. is &quot;overshot,&quot; and the assignment
  # occurs in the global environment instead; no numeric position seems to work
  exec(function() {
    'foo' %&gt;% assign(x = 'bar', pos = 1)
    exists('bar', inherits = FALSE)
  })
  #&gt; [1] FALSE
  rm(bar)
  
  # Works, presumably because the function's exec. env. happens to be exactly 6
  # frames back from the environment in which the `assign()` call is evaluated, in
  # this specific case
  exec(function() {
    'foo' %&gt;% assign(x = 'bar', pos = caller_env(6))
    print(exists('bar', inherits = FALSE))
    print(bar)
  })
  #&gt; [1] TRUE
  #&gt; [1] &quot;foo&quot;
  
  # Fails for unknown reasons - maybe there's a `caller_env()` value that would
  # work, but I haven't found it
  exec(function() {
    list &lt;- list(bar = 'foo')
    list2env(list, envir = caller_env())
    exists('bar', inherits = FALSE)
  })
  #&gt; [1] FALSE
  </code></pre>
  <p><sup>Created on 2020-10-27 by the <a href="https://reprex.tidyverse.org" rel="nofollow noreferrer">reprex package</a> (v0.3.0)</sup></p>