Exactly — my favorite example of this is data.frames and lists. Data.frames differ from matrices because they store columns of different types — unlike matrices, each column can contain a different type. What R data structure can contain objects of different types? Lists! So data.frames are lists:
> l <- list(col1=rnorm(5), col2=sample(c('a', 'b'), 5, replace=TRUE))
> class(l)
[1] "list"
> typeof(l)
[1] "list"
> is.list(l)
[1] TRUE
> d <- data.frame(col1=rnorm(5), col2=sample(c('a', 'b'), 5, replace=TRUE))
> class(d)
[1] "data.frame"
> is.list(d)
[1] TRUE
> typeof(d)
[1] "list"
Data.frames are simply R lists with class "data.frame" (and row.names — these are required). In fact, you can create an R data.frame from a list by just changing the class from "list" to "data.frame" and adding row names:
> class(l) <- "data.frame"
> row.names(l) <- 1:5 # we need row.names
> l
col1 col2
1 -0.3052572 a
2 1.6734096 a
3 1.1435472 a
4 -1.1576587 a
5 -1.0802156 a
> is.data.frame(l)
[1] TRUE
Hope this helps tie some loose ends! R's data structures are strange at first, but actually quite elegant in the way they all connect with each other.
Vince