title: Extracting sub-elements from list of lists vs list of vectors using lapply
body: <p>How does <code>lapply</code> extract sub-elements from a list? More specifically, how does <code>lapply</code> extract sub-elements from a list of lists versus a list of vectors? Even more specifically, suppose I have the following:</p>
  
  <pre><code>my_list_of_lists &lt;- list(list(a = 1, b = 2), list(a = 2, c = 3), list(b = 4, c = 5))
  my_list_of_lists[[1]][["a"]] # just checking
  # [1] 1 
  # that's what I expected
  </code></pre>
  
  <p>and apply the following: </p>
  
  <pre><code>lapply(my_list_of_lists, function(x) x[["a"]]) 
  # [[1]]
  # [1] 1
  # 
  # [[2]]
  # [1] 2
  # 
  # [[3]]
  # NULL
  </code></pre>
  
  <p>So <code>lapply</code> extracts the <code>a</code> element from each of the 3 sublists, returning each in its own list, contained in the length=3 list. At this point, my mental model is the following: <code>lapply</code> applies <code>FUN</code> to each element of <code>my_list</code>, returning <code>FUN(my_list[[i]])</code> for <code>i</code> in <code>1:3</code>. Great! So I expect my mental model should work for lists of vectors as well. For example,</p>
  
  <pre><code>my_list_of_vecs &lt;- list(c(a = 1, b = 2), c(a = 2, c = 3), c(b = 4, c = 5))
  my_list_of_vecs[[1]][["a"]] # Just checking
  # [1] 1
  # that's what I expected
  </code></pre>
  
  <p>and apply the following:</p>
  
  <pre><code>lapply(my_list_of_vecs, function(x) x[["a"]]) 
  # Error in x[["a"]] : subscript out of bounds
  # Wait...What!?
  </code></pre>
  
  <p>What's going on here!? Shouldn't this just work? I found a section in <code>help(lapply)</code> which might be relevant:</p>
  
  <blockquote>
    <p>For historical reasons, the calls created by lapply are unevaluated,
    and code has been written (e.g., bquote) that relies on this. This
    means that the recorded call is always of the form FUN(X[[i]], ...),
    with i replaced by the current (integer or double) index. This is not
    normally a problem, but it can be if FUN uses sys.call or match.call
    or if it is a primitive function that makes use of the call. This
    means that it is often safer to call primitive functions with a
    wrapper, so that e.g. lapply(ll, function(x) is.numeric(x)) is
    required to ensure that method dispatch for is.numeric occurs
    correctly.</p>
  </blockquote>
  
  <p>I really don't know how to make sense of this.</p>
  
  <p>I think it's related to the fact that you can use both <code>[[</code> and <code>[</code> extraction of single elements from a vector but you can ONLY use <code>[</code> extraction of ranges of elements. For example,</p>
  
  <pre><code>my_list_of_vecs[[1]][1:2]
  # a b 
  # 1 2
  my_list_of_vecs[[1]][[1:2]]
  # Error in my_list_of_vecs[[1]][[1:2]] : 
  #   attempt to select more than one element in vectorIndex
  </code></pre>
  
  <p>So under the hood, <code>lapply</code> must be using <code>function(x) x[["a"]]</code> over a range. Is that right? </p>
  
  <p>Debugging doesn't help me here since these functions rely on <code>.Internal</code> functions. </p>