r-lib / sloop Goto Github PK
View Code? Open in Web Editor NEWS language OOP ⛵️
Home Page: https://sloop.r-lib.org
S language OOP ⛵️
Home Page: https://sloop.r-lib.org
(Probably due to a change in R 4.0; I discovered this when solving the regarding exercise in Adv R)
# Output in R 4.0.3
x <- structure(1:10, class = "test")
sloop::s3_dispatch(t(x))
#> => t.test
#> * t.default
t(x)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 1 2 3 4 5 6 7 8 9 10
#> attr(,"class")
#> [1] "test"
t.test(x)
#>
#> One Sample t-test
#>
#> data: x
#> t = 5.7446, df = 9, p-value = 0.0002782
#> alternative hypothesis: true mean is not equal to 0
#> 95 percent confidence interval:
#> 3.334149 7.665851
#> sample estimates:
#> mean of x
#> 5.5
Created on 2020-12-31 by the reprex package (v0.3.0)
library(sloop)
x1 <- 1:5
s3_dispatch(x1[1])
#> -> [.integer
#> [.numeric
#> [.default
#> * [
x2 <- structure(x1, class = "integer")
s3_dispatch(x2[1])
#> -> [.integer
#> [.default
#> * [
Created on 2018-10-03 by the reprex package (v0.2.1)
Should be:
x1 <- 1:5
s3_dispatch(x1[1])
#> -> [
inherits_data.frame()
etc
For example,
library(sloop)
x <- 1:5
y <- factor(letters[1:5])
sloop::s3_dispatch(summary(x))
#> summary.integer
#> summary.numeric
#> => summary.default
sloop::s3_dispatch(summary(y))
#> => summary.factor
#> * summary.default
What does =>
indicate? *
, ->
? In the console, some functions appear greyed out, what does that mean?
This seems to be done partially in the README but it needs to make it into the docs.
Once I've recalled exactly what the difference is (I think it's that they don't dispatch if is.object()
isn't true)
Maybe essthree or sthree
The master
branch of this repository will soon be renamed to main
, as part of a coordinated change across several GitHub organizations (including, but not limited to: tidyverse, r-lib, tidymodels, and sol-eng). We anticipate this will happen by the end of September 2021.
That will be preceded by a release of the usethis package, which will gain some functionality around detecting and adapting to a renamed default branch. There will also be a blog post at the time of this master
--> main
change.
The purpose of this issue is to:
message id: euphoric_snowdog
2020
usethis::use_package_doc()
@importFrom
directives here.usethis::use_import_from()
is handy for this.usethis::use_testthat(3)
and upgrade to 3e, testthat 3e vignetteR/
files and test/
files for workflow happiness.usethis::use_r()
include a helpful script.usethis::rename_files()
may be be useful.2021
usethis::use_tidy_description()
usethis::use_tidy_dependencies()
usethis::use_tidy_github_actions()
and update artisanal actions to use setup-r-dependencies
cran-comments.md
Authors@R
of DESCRIPTION like so, if appropriate:person("RStudio", role = c("cph", "fnd"))
2022
usethis::use_tidy_coc()
master
--> main
issuesdevelopment
is mode: auto
in pkgdown configusethis::use_lifecycle()
2023
Necessary:
person(given = "Posit Software, PBC", role = c("cph", "fnd"))
Run devtools::document()
to re-generate package-level help topic with DESCRIPTION changesuse_tidy_logo()
usethis::use_tidy_coc()
usethis::use_tidy_github_actions()
Optional:
pak::pak("org/pkg")
over devtools::install_github("org/pkg")
in READMEuse_tidy_dependencies()
and/or replace compat files with use_standalone()
use_standalone("r-lib/rlang", "types-check")
instead of home grown argument checkersCreated on 2023-10-30 with usethis::use_tidy_upkeep_issue()
, using usethis v2.2.2.9000
sloop::s3_dispatch(vctrs::vec_arith("+", 2, 3))
#> Error: Mapped vectors must have consistent lengths:
#> * `.x` has length 3
#> * `.y` has length 2
Not sure if it is better to handle this case specially or to modify the check
if (!is_call(call)) {
stop("`call` must be a function call", call. = FALSE)
}
p. <- quote((.))
sloop::s3_class(p.)
#> [1] "(" "call"
foo <- function(x) UseMethod("foo")
foo.call <- function(x) "produced inside foo.call"
foo(p.)
#> Error in UseMethod("foo"): no applicable method for 'foo' applied to an object of class "("
`foo.(` <- function(x) "produced inside foo.("
foo(p.)
#> [1] "produced inside foo.("
Created on 2019-11-22 by the reprex package (v0.3.0)
From combining pryr::method_from_call()
with sloop::s3_dispatch()
Prepare for release:
devtools::check_win_devel()
rhub::check_for_cran()
Perform release:
devtools::check_win_devel()
(again!)devtools::submit_cran()
pkgdown::build_site()
Wait for CRAN...
Template from r-lib/usethis#338
Is the fact that the second line generates an error a bug or a feature? I'm not sure how to interpret this...
ftype(all.equal)
s3_get_method(all.equal(1, 1))
The generic should dispatch in cbind.default, why didn't it happen? The output in s3_dispatch() is correct, as I would expect. But that didn't happen when I use the generic. See the code below.
Code:
cbind.default <- function(x, ...) "Test!"
x <- 1:10
sloop::s3_dispatch(cbind(structure(x, class = "numeric")))
cbind(structure(x, class = "numeric"))
Example (Output):
cbind.default <- function(x, ...) "Test!"
x <- 1:10
sloop::s3_dispatch(cbind(structure(x, class = "numeric")))
cbind.numeric
=> cbind.default
cbind(structure(x, class = "numeric"))
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
[6,] 6
[7,] 7
[8,] 8
[9,] 9
[10,] 10
Jumping off of hadley/adv-r#1148, attribute retention seems like an important thing.
sloop::reconstruct()
is a great helper in that regard.
However, it's hard to foresee for users (or, more likely, package developers) for which generics (other than, say, dplyr::mutate()
some mutate.myClass()
would have to be built.
You mention in adv-r that e.g. dplyr will do this out of the box at some point (which is fantastic).
However, this is unlikely for base functions such as subset()
and friends.
It also seems a bit of a duplicate effort to build mutate.myClassA()
for pkgA and have someone else build mutate.myClassB()
for pkgB when essentially, all mutate.xClass()
do the same thing.
I was wondering whether it might therefore make sense to combine sloop::reconstruct with sticky::sticky (or factor this out to a separate package):
sticky
) for objects which are supposed to retain their attributes.subset.sticky()
methods the frequently used (base) functions which are unlikely to get such methods from their developers (which would be preferable).reconstruct.default()
which pkg developers can fall back on when developing their own some_function.myClass()
.I obviously have no business suggesting this and too little understanding of R plumbing for this, but I noticed these two related efforts and thought I'd write this up here.
Would also be happy to chip in, but need some direction.
Something like:
library(tidyverse)
methods("format") %>%
attr(., "info") %>%
as_tibble() %>%
rownames_to_column("method") %>%
mutate(class = stringr::str_split_fixed(method, "\\.", 2)[, 2]) %>%
select(generic, class, visible, from)
May want to consider implementing methods()
from scratch — will help understand precise semantics of method lookup.
Prepare for release:
devtools::check()
devtools::check_win_devel()
rhub::check_for_cran()
revdepcheck::revdep_check(num_workers = 4)
Submit to CRAN:
usethis::use_version()
cran-comments.md
devtools::submit_cran()
Wait for CRAN...
usethis::use_github_release()
usethis::use_dev_version()
Now that vctrs exists and fully fleshes out what you need to create S3 vectors, I think it's more clear that sloop should be a package aimed at interactive exploration, including show case of what implement of base R vectors might look like, if we rewrote them from scratch.
To this end, will remove reconstruct()
(now vctrs::vec_recast()
), and the new_s3_*()
family of functions (since they're only thin wrappers, and if you need them yourself you might as well rebind).
As in your book https://adv-r.hadley.nz/s3.html#finding-methods
If there are no existing methods, s4_methods_class
, as a wrapper of utils::methods
,
is not expected to throw an error:
setClass("virtualA", contains = "VIRTUAL")
s4_methods_class("virtualA")
#> Error in `$<-.data.frame`(`*tmp*`, class, value = "virtualA") :
# replacement has 1 row, data has 0
However,
attr(utils::methods(class = "virtualA"), "info")
#> [1] visible from generic isS4
# <0 rows> (or 0-length row.names)
Maybe sloop:::methods_class
can do a check for row number or other way to avoid the error...
I know Github handles redirects automatically, but it might confuse people to point them to devtools::install_github("hadley/S3")
. Should be updated to devtools::install_github("hadley/sloop")
If I refer to a function via a variable, the class
column of s3_methods_generic
isn't what I'd expect.
this_func <- mean
sloop::s3_methods_generic("this_func")
#> Warning in .S3methods(generic.function, class, envir): generic function
#> 'this_func' dispatches methods for generic 'mean'
#> # A tibble: 6 x 4
#> generic class visible source
#> <chr> <chr> <lgl> <chr>
#> 1 mean mean.Date TRUE base
#> 2 mean mean.default TRUE base
#> 3 mean mean.difftime TRUE base
#> 4 mean mean.POSIXct TRUE base
#> 5 mean mean.POSIXlt TRUE base
#> 6 mean mean.quosure FALSE registered S3method for mean
sloop::s3_methods_generic("mean")
#> # A tibble: 7 x 4
#> generic class visible source
#> <chr> <chr> <lgl> <chr>
#> 1 mean Date TRUE base
#> 2 mean default TRUE base
#> 3 mean difftime TRUE base
#> 4 mean POSIXct TRUE base
#> 5 mean POSIXlt TRUE base
#> 6 mean quosure FALSE registered S3method
#> 7 mean vctrs_vctr FALSE registered S3method
We already have the "generic" column from utils::method
, should it use that for generating the "class" column (rather than x
)?
I can PR if there isn't a reason to use the generic_esc
that I'm not thinking of; using info from methods seems safer.
So when you ask about s3_dispatch(sum(Sys.time()))
you see Summary.POSIXct
etc
as in e.g. hms might be a good fit for this package: r-spatial/sf#710.
https://github.com/tidyverse/hms/blob/c0cfc010566c6d6fa50e38201b14142a0aea8b29/R/zzz.R#L8-L30
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.