J. Mini
J. Mini

Reputation: 1610

$ is an internal generic function, so how did the tibble package extend it?

Because it is on the list of Internal Generic Functions, I know that $ is an internal generic function. To my knowledge, this means that it cannot be extended using S3. Despite this, it is well-known that $ behaves differently for tibbles as it does data frames, implying that the developer of the tibble package have done what I believed to be impossible. How was this achieved? I tried to get the code for $.tibble up in my IDE, but tibble::"$".tibble returned nothing.

Upvotes: 1

Views: 90

Answers (2)

MrFlick
MrFlick

Reputation: 206596

You can change behavior for internal generics if the first parameter is an object (is.object(x)==TRUE). A tibble is an object. Most user created S3 classes are. Your problem before was you were trying to change the behavior for a matrix and a matrix is not an "object" so you cannot change the dispatch for internal generics for such objects.

Upvotes: 1

G. Grothendieck
G. Grothendieck

Reputation: 270348

Use the following to find examples in the base of R and in any loaded packages. (If the tibble package were loaded it would also list any $ methods in it although be aware that the class name of a tibble is not tibble .)

methods("$")
## [1] $,envRefClass-method        $,refObjectGenerator-method
## [3] $.bibentry*                 $.DLLInfo                  
## [5] $.package_version           $.person*   

getAnywhere("$.bibentry")         
## ...snip...

library(tibble)
tib <- tibble()
class(tib)
## [1] "tbl_df"     "tbl"        "data.frame"
getAnywhere("$.tbl_df")
## ..snip...

Here are some more examples assuming you have installed the relevant packages:

zoo:::"$.zoo"
proto:::"$.proto"
gsubfn:::"$.fn"
dyn:::"$.dyn"

or:

A key consideration is that the part after the $ is not evaluated even if you extend it.

Upvotes: 1

Related Questions