39

I've seen the function lapply used in R to extract elements from matrices that exist in a list of matrices.

E.g. I have a list of 3 (2x2) matrices, and I want to extract element [1,2] from each of those 3 matrices.

The code: list1 = lapply(mylist, '[', 1,2) works just fine. It returns a list with those 3 elements.

I am trying to research what this is exactly doing. Google hasn't helped and using ?'[' in the R help isn't too explanatory. I don't see how '[' is a function in R, so the code is not intuitive.

Saksham
  • 9,037
  • 7
  • 45
  • 73
AdamC
  • 415
  • 1
  • 4
  • 4
  • 1
    Related: http://stackoverflow.com/questions/10449366/levels-what-sorcery-is-this – Ari B. Friedman Oct 09 '13 at 00:40
  • 3
    As others have pointed out, `[` is most definitely a function. There are also assignment functions (e.g.: `[<-`) which step in when you use the many variations on `<-` (as @AriB.Friedman notes in that link). E.g., try something like these 2 commands: `x <- 1:5; "[<-"(x,1,10);` – thelatemail Oct 09 '13 at 02:42
  • 5
    **Everything** in R is an object... and if it *does* something, then the type of object is function. – Gregor Thomas Apr 21 '15 at 23:16

2 Answers2

46

The square brackets are in fact a function whose first argument is the object being subsetted. Subsequent arguments are the index to that subset.

# For example, if M is a matrix
M[1, 2]  # extracts the element at row 1, col 2
# is the same as 
`[`(M, 1, 2)
# Try them! 

Now, Have a look at the arguments to lapply:

args(lapply)
# function (X, FUN, ...) 

Everything represented in those dots gets passed on to the function FUN as arguments.

Thus, when FUN="[", the first argument to "[" is the current element of the list (being iterated over), ie, the object being subsetted. While the subsequent arguments are the indexes to "["

Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
  • Is there a list available with these "special" functions like `"["`, `"("`? Is there also a function `"{"`? At the end, my question asks how can I get this kind of knowledge? – giordano Sep 30 '21 at 08:29
24

Operators in R are just functions.

These are equivalent:

> x <- list(a=1,b=2)
> x[1]
$a
[1] 1

> `[`(x,1)
$a
[1] 1

The backticks are necessary only to prevent interpretation by the parser (e.g. to tell it it's a function name not to start interpreting the [ prematurely).

Being a function, it follows the same object-oriented rules (in this case, S3) as everything else.

> methods(`[`)
 [1] [.acf*             [.arrow*           [.AsIs             [.bibentry*        [.cluster*         [.data.frame       [.data.table*     
 [8] [.Date             [.difftime         [.envlist*         [.factor           [.formula*         [.fractions*       [.getAnywhere*    
[15] [.gList*           [.gpar*            [.gtable*          [.hexmode          [.idf*             [.indexed*         [.insensitive*    
[22] [.ITime*           [.listof           [.noquote          [.numeric_version  [.octmode          [.pdf_doc*         [.person*         
[29] [.POSIXct          [.POSIXlt          [.quoted*          [.raster*          [.roman*           [.shingle*         [.simple.list     
[36] [.split*           [.terms*           [.trellis*         [.ts*              [.tskernel*        [.uneval*          [.unit*           
[43] [.unit.arithmetic* [.unit.list*       [.vpPath*         

   Non-visible functions are asterisked

+, =, etc. and other operators all work this way as well.

Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
  • 2
    Nice explanation - to give an example of the 'other operators', `"/"(1,2)` and `1/2` and `do.call("/",list(1,2))` all give the same result. – thelatemail Oct 09 '13 at 02:35
  • 1
    Regarding the asterisked functions, see [How can I view the source code for a function?](http://stackoverflow.com/a/19226817/1191259) – Frank Oct 09 '13 at 02:48
  • 2
    @thelatemail In base, there's `Reduce('/',list(1,2))`, `Map('/',1,2)` and all the *`apply`s that take functions as arguments, too, and maybe more (?)... – Frank Oct 09 '13 at 02:52