How to Correctly Use Lists in R?
Question: Brief background: Many (most?) contemporary programming languages in
widespread use have at least a handful of ADTs [abstract data types] in
common, in particular,

  * **string** (a sequence comprised of characters)

  * **list** (an ordered collection of values), and

  * **map-based type** (an unordered array that maps keys to values)

In the R programming language, the first two are implemented as `character`
and `vector`, respectively.

When I began learning R, two things were obvious almost from the start: `list`
is the most important data type in R (because it is the parent class for the R
`data.frame`), and second, I just couldn't understand how they worked, at
least not well enough to use them correctly in my code.

For one thing, it seemed to me that R's `list` data type was a straightforward
implementation of the map ADT (`dictionary` in Python, `NSMutableDictionary`
in Objective C, `hash` in Perl and Ruby, `object literal` in Javascript, and
so forth).

For instance, you create them just like you would a Python dictionary, by
passing key-value pairs to a constructor (which in Python is `dict` not
`list`):

    
    
    x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
    

And you access the items of an R List just like you would those of a Python
dictionary, e.g., x['ev1']. Likewise, you can retrieve just the 'keys' or just
the 'values' by:

    
    
    names(x)    # fetch just the 'keys' of an R list
    # [1] "ev1" "ev2" "rv"
    
    unlist(x)   # fetch just the 'values' of an R list
    #   ev1       ev2        rv 
    #  "10"      "15" "Group 1" 
    
    x = list("a"=6, "b"=9, "c"=3)  
    
    sum(unlist(x))
    # [1] 18
    

but R `list`s are also **_unlike_** other map-type ADTs (from among the
languages I've learned anyway). My guess is that this is a consequence of the
initial spec for S, i.e., an intention to design a data/statistics DSL
[domain-specific language] from the ground-up.

_three_ significant differences between R `list`s and mapping types in other
languages in widespread use (e.g,. Python, Perl, JavaScript):

_first_ , `list`s in R are an _ordered_ collection, just like vectors, even
though the values are keyed (ie, the keys can be any hashable value not just
sequential integers). Nearly always, the mapping data type in other languages
is _unordered_.

_second_ , `list`s can be returned from functions even though you never passed
in a `list` when you called the function, and _even though_ the function that
returned the `list` doesn't contain an (explicit) `list` constructor (Of
course, you can deal with this in practice by wrapping the returned result in
a call to `unlist`):

    
    
    x = strsplit(LETTERS[1:10], "")     # passing in an object of type 'character'
    
    class(x)                            # returns 'list', not a vector of length 2
    # [1] list
    

A _third_ peculiar feature of R's `list`s: it doesn't seem that they can be
members of another ADT, and if you try to do that then the primary container
is coerced to a `list`. E.g.,

    
    
    x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
    
    class(x)
    # [1] list
    

my intention here is not to criticize the language or how it is documented;
likewise, I'm not suggesting there is anything wrong with the `list` data
structure or how it behaves. All I'm after is to correct is my understanding
of how they work so I can correctly use them in my code.

Here are the sorts of things I'd like to better understand:

  * What are the rules which determine when a function call will return a `list` (e.g., `strsplit` expression recited above)?

  * If I don't explicitly assign names to a `list` (e.g., `list(10,20,30,40)`) are the default names just sequential integers beginning with 1? (I assume, but I am far from certain that the answer is yes, otherwise we wouldn't be able to coerce this type of `list` to a vector w/ a call to `unlist`.

  * why do these two different operators, `[]`, and `[[]]`, return the _same_ result?

`x = list(1, 2, 3, 4)`

both expressions return "1":

`x[1]`

`x[[1]]`

  * why do these two expressions **not** return the same result?

`x = list(1, 2, 3, 4)`

`x2 = list(1:4)`

Please don't point me to the R Documentation
([`?list`](http://www.inside-r.org/r-doc/base/list),
[`R-intro`](http://cran.r-project.org/doc/manuals/r-devel/R-intro.html#Lists))--I
have read it carefully and it does not help me answer the type of questions I
recited just above.

(lastly, I recently learned of and began using an R Package (available on
CRAN) called [`hash`](http://mran.revolutionanalytics.com/packages/info/?hash)
which implements _conventional_ map-type behavior via an S4 class; I can
certainly recommend this Package.)


Answer: Just to address the last part of your question, since that really points out
the difference between a `list` and `vector` in R:

> Why do these two expressions not return the same result?
>
> x = list(1, 2, 3, 4); x2 = list(1:4)

A list can contain any other class as each element. So you can have a list
where the first element is a character vector, the second is a data frame,
etc. In this case, you have created two different lists. x has four vectors,
each of length 1. x2 has 1 vector of length 4:

    
    
    > length(x[[1]])
    [1] 1
    > length(x2[[1]])
    [1] 4
    

So these are completely different lists.

R lists are very much like [a hash
map](http://en.wikipedia.org/wiki/Hash_table) data structure in that each
index value can be associated with any object. Here's a simple example of a
list that contains 3 different classes (including a function):

    
    
    > complicated.list <- list("a"=1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
    > lapply(complicated.list, class)
    $a
    [1] "integer"
    $b
    [1] "integer"
    $c
    [1] "matrix"
    $d
    [1] "function"
    

Given that the last element is the search function, I can call it like so:

    
    
    > complicated.list[["d"]]()
    [1] ".GlobalEnv" ...
    

As a final comment on this: it should be noted that a `data.frame` is really a
list (from the data.frame documentation):

> A data frame is a list of variables of the same number of rows with unique
> row names, given class ‘"data.frame"’

That's why columns in a data.frame can have different data types, while
columns in a matrix cannot. As an example, here I try to create a matrix with
numbers and characters:

    
    
    > a <- 1:4
    > class(a)
    [1] "integer"
    > b <- c("a","b","c","d")
    > d <- cbind(a, b)
    > d
     a   b  
    [1,] "1" "a"
    [2,] "2" "b"
    [3,] "3" "c"
    [4,] "4" "d"
    > class(d[,1])
    [1] "character"
    

Note how I cannot change the data type in the first column to numeric because
the second column has characters:

    
    
    > d[,1] <- as.numeric(d[,1])
    > class(d[,1])
    [1] "character"
    

