r-lib / lobstr Goto Github PK
View Code? Open in Web Editor NEWUnderstanding complex R objects with tools similar to str()
Home Page: https://lobstr.r-lib.org/
License: Other
Understanding complex R objects with tools similar to str()
Home Page: https://lobstr.r-lib.org/
License: Other
lobstr::ast(5i)
#> 0+5i
Created on 2018-10-29 by the reprex package (v0.2.1)
e.g.
lobstr::sxp(f(1))
█─LANGSXP <0x12345>
├─SYMSXP <0x12345> `f`
└─INTSXP <0x12345> [1]
lobstr::sxp(f(1), pairlist = TRUE)
█─LANGSXP <0x12345>
├─SYMSXP <0x12345> `f`
└─█─LANGSXP <0x12345>
├─INTSXP <0x12345> [1]
└─NILSXP
lobstr::sxp(f(1), pairlist = TRUE, symbol = TRUE)
█─LANGSXP <0x12345>
├─█─SYMSXP <0x12345> `f`
│ └─STRSXP <0x12345> "f"
└─█─LANGSXP <0x12345>
├─INTSXP <0x12345> [1]
└─NILSXP
e <- new.env(parent = emptyenv())
e$e <- e
lobstr::str(e)
█─ENVSXP <0x12345>
└─e = █─ENVSXP <0x12345> ...
Would either take expression + env, or quosure.
Prints parent envs at end, and printing an indexing into them with numbers/colours next to each symbol.
Since a lot of the point of this package seems to be to visualize the structure of objects, it would be nice to have a plot method to show the AST/CST as a network (either with ggraph or threejs).
It looks like ast()
returns a character vector though; so the package might need a data frame representation of the tree first. (Or it could be done from utils::getParseData()
.)
'X' makes it hard to read. The blocks on linux/mac looks much better. I think the windows font problem was recently fixed in the skimr package.
Edit: Here is the skimr code to fix windows unicode https://github.com/ropenscilabs/skimr/blob/master/R/utils.R
Prepare for release:
usethis::use_cran_comments()
devtools::check()
devtools::check_win_devel()
rhub::check_for_cran()
rhub::check(platform = 'ubuntu-rchk')
rhub::check_with_sanitizers()
Submit to CRAN:
usethis::use_version('minor')
cran-comments.md
devtools::submit_cran()
Wait for CRAN...
usethis::use_github_release()
usethis::use_dev_version()
library(rlang)
library(lobstr)
q1 <- new_quosure(expr(x), env(x = 1))
q2 <- new_quosure(expr(x), env(x = 10))
lobstr::ast(!!q1 + !!q2)
#> Warning: `quo_expr()` is soft-deprecated as of rlang 0.2.0.
#> Please use `quo_squash()` instead
#> This warning is displayed once per session.
#> █─`+`
#> ├─x
#> └─x
Created on 2018-11-08 by the reprex package (v0.2.1)
(Probably what I was thinking in #6)
mem_tree()
The carrier package used to do format(pryr::object_size(x))
. This has stopped working when pryr started to create lobstr objects, because these don't have a format method.
Maybe lobstr::sxp()
?
As it's (understandably) causing confusion
Prepare for release:
devtools::check()
Submit to CRAN:
usethis::use_version('patch')
cran-comments.md
devtools::submit_cran()
Wait for CRAN...
usethis::use_github_release()
usethis::use_dev_version()
When trying to use object_size to get the true size of a "hash" object (instantiated with library(hash)" I get the following error:
class(hash_table)
[1] "hash"
attr(,"package")
[1] "hash"
str(hash_table)
Formal class 'hash' [package "hash"] with 1 slot
..@ .xData:<environment: 0x24f72ec8>
object_size(hash_table)
type: 17
Error: Unimplemented type
When I try to run the example in Exercise 2 of Section 2.4.1 in the second edition of Advanced R, I am getting a segfault on a call to lobstr::obj_size
. The example code is shown below. I would be happy to work on a fix if it turns out to not be just a dependency issue or something similar, and given some direction.
devtools::session_info("lobstr")
#> ─ Session info ──────────────────────────────────────────────────────────
#> setting value
#> version R version 3.4.4 (2018-03-15)
#> os Ubuntu 16.04.5 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language en_US
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/New_York
#> date 2018-11-17
#>
#> ─ Packages ──────────────────────────────────────────────────────────────
#> package * version date lib source
#> crayon 1.3.4 2017-09-16 [1] CRAN (R 3.4.1)
#> lobstr 1.0.0 2018-11-04 [1] CRAN (R 3.4.4)
#> Rcpp 1.0.0 2018-11-07 [1] CRAN (R 3.4.4)
#> rlang 0.3.0.1 2018-10-25 [1] CRAN (R 3.4.4)
#>
#> [1] /home/dpritch/R/x86_64-pc-linux-gnu-library/3.4
#> [2] /usr/local/lib/R/site-library
#> [3] /usr/lib/R/site-library
#> [4] /usr/lib/R/library
x <- list(mean, sd, var)
lobstr::obj_size(x)
#> *** caught segfault ***
#> address 0x2, cause 'memory not mapped'
#>
#> Traceback:
#> 1: .Call(`_lobstr_obj_size_`, objects, base_env, sizeof_node, sizeof_vector)
#> 2: obj_size_(dots, env, size_node(), size_vector())
#> 3: lobstr::obj_size(x)
#> 4: eval(expr, envir, enclos)
#> 5: eval(expr, envir, enclos)
#> 6: withVisible(eval(expr, envir, enclos))
#> 7: withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, error = eHandler, message = mHandler)
#> 8: doTryCatch(return(expr), name, parentenv, handler)
#> 9: tryCatchOne(expr, names, parentenv, handlers[[1L]])
#> 10: tryCatchList(expr, classes, parentenv, handlers)
#> 11: tryCatch(expr, error = function(e) { call <- conditionCall(e) if (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix <- paste("Error in", dcall, ": ") LONG <- 7
I am chasing memory leaks and/or high memory fragmentation in a Shiny app. I have noticed that after closing the Shiny app and returning to the R prompt, gc()
still reports some 3.8 GB of memory used even after emptying all environments (except baseenv()
) and unloading all namespaces, which is quite a bit. (For context, Linux top
reports some 11 GB of virtual memory used.)
I have started looking at the remaining elements in baseenv()
, and found that almost all of the memory is in baseenv()$.__S3MethodsTable__.
(disclaimer: I have no idea what this is for and why this could ever be this big):
lobstr::obj_size(baseenv()$.__S3MethodsTable__.)
# 3,314,445,280 B
So I went ahead to see which of its elements is the culprit:
sizes <- lapply(names(baseenv()$.__S3MethodsTable__.), \(name) lobstr::obj_size(baseenv()$.__S3MethodsTable__.[[name]]))
names(sizes) <- names(baseenv()$.__S3MethodsTable__.)
sizes <- sizes[order(unlist(sizes))]
To my astonishment, after I have done this, the reported size of baseenv()$.__S3MethodsTable__.
has drastically decreased:
lobstr::obj_size(baseenv()$.__S3MethodsTable__.)
# 157,085,600 B
The same happens when I inspect members of baseenv()$.__S3MethodsTable__.
:
sizes
# $`[[.SQL`
# 93,406,504 B
#
# $`[.SQL`
# 93,406,504 B
#
# $toString.Id
# 93,411,712 B
lobstr::obj_size(baseenv()$.__S3MethodsTable__.$toString.Id)
# 93,411,712 B
baseenv()$.__S3MethodsTable__.$toString.Id
# function(x, ...) {
# paste0("<Id> ", paste0(names(x@name), " = ", x@name, collapse = ", "))
# }
# <bytecode: 0x55a1f4ea97c8>
# <environment: namespace:DBI>
lobstr::obj_size(baseenv()$.__S3MethodsTable__.$toString.Id)
# 297,264 B
What is going on here? I almost feel like the memory leak is playing whac-a-mole. Is this a bug in obj_size
, expected behavior, or actually a sign of memory leaks?
Interestingly, in a clean R session, this element has yet another size: (That was comparing Windows with Linux - it's consistent on Linux.)
library(DBI)
baseenv()$.__S3MethodsTable__.$toString.Id
# function (x, ...)
# {
# paste0("<Id> ", paste0(names(x@name), " = ", x@name, collapse = ", "))
# }
# <bytecode: 0x00000000194d22f0>
# <environment: namespace:DBI>
lobstr::obj_size(baseenv()$.__S3MethodsTable__.$toString.Id)
# 4,320 B
Hi,
My aim is to replace &
with function min()
and replace |
with max()
. So, a & (b | c)
should be rewritten as min(a, max(b,c))
. I thought modifying the syntax tree is the way to go. Is it possible to modify ast()
output and then convert back into an expression?
I'm sharing a small example:
a <- 5
b <- 10
c <- 4
express <- a & (b | c)
express_adv <- (c & b) & (a & (b | c))
The rewritten express
should evaluate to 5
and express_adv
should evaluate to 4
. Expected expressions are :
min(a, max(b,c)) # modified express
min( min(c,b), min(a, max(b,c))) # modified express_adv
So, this is before:
ast( a & (b | c) )
█─`&`
├─a
└─█─`(`
└─█─`|`
├─b
└─c
and this is after:
ast(min(a,(max(b,c))))
█─min
├─a
└─█─`(`
└─█─max
├─b
└─c
I'm seeing this error pop up inside of RStudio when attempting to call lobstr::obj_size()
. I'm working on attempting to make a reprex. Just wanted to see if this is a known issue that anyone else has come across:
Error in obj_size_(dots, env, size_node(), size_vector()) :
bad binding access
Calls: obj_size -> obj_size_
Backtrace:
█
1. └─lobstr::obj_size(object)
2. └─lobstr:::obj_size_(dots, env, size_node(), size_vector())
I'm having a hard time installing the development version of packages on my Windows machine. As far as I can tell, the CRAN version of rlang
is up-to-date enough that removing rlang
from Remotes
will fix these installation issues for lobstr
.
I imagine the changes in devtools
will eventually fix the errors in the dev version of rlang
(and by extension lobstr
) but they currently don't work for Windows. Not filing the issue in those packages because it seems like the work may already be in progress.
Not entirely sure how to reprex installation issues, but here's what I've got:
> devtools::find_rtools()
WARNING: Rtools is required to build R packages, but no version of Rtools compatible with R 3.5.1 was found. (Only the following incompatible version(s) of Rtools were found:3.4)
Please download and install the appropriate version of Rtools from http://cran.r-project.org/bin/windows/Rtools/.
> pkgbuild::find_rtools()
[1] TRUE
> devtools::install_github("r-lib/rlang")
Using GitHub PAT from envvar GITHUB_PAT
Downloading GitHub repo r-lib/rlang@master
from URL https://api.github.com/repos/r-lib/rlang/zipball/master
WARNING: Rtools is required to build R packages, but no version of Rtools compatible with R 3.5.1 was found. (Only the following incompatible version(s) of Rtools were found:3.4)
Please download and install the appropriate version of Rtools from http://cran.r-project.org/bin/windows/Rtools/.
Installing rlang
These seem to be related:
r-lib/devtools#1772
r-lib/rlang#510
Let me know if there's something I can do on my end to help with this!
Prepare for release:
devtools::check()
devtools::check_win_devel()
rhub::check_for_cran()
rhub::check(platform = 'ubuntu-rchk')
rhub::check_with_sanitizers()
revdepcheck::revdep_check(num_workers = 4)
Submit to CRAN:
usethis::use_version('1.0.1')
devtools::check_win_devel()
(again!)devtools::submit_cran()
Wait for CRAN...
usethis::use_release_tag()
usethis::use_dev_version()
Sorry I couldn't understand the difference from the documentation
library(lobstr)
x <- 1:1e6
y <- list(x, x, x)
ref(y)
#> █ [1:0x7fee181b95e8] <list>
#> ├─[2:0x7fee142b72a8] <int>
#> ├─[2:0x7fee142b72a8]
#> └─[2:0x7fee142b72a8]
object.size(x)
#> 4000048 bytes
obj_size(x)
#> 680 B
object.size(y)
#> 12000224 bytes
obj_size(y)
#> 760 B
ref(x)
#> [1:0x7fee142b72a8] <int>
ref(y)
#> █ [1:0x7fee181b95e8] <list>
#> ├─[2:0x7fee142b72a8] <int>
#> ├─[2:0x7fee142b72a8]
#> └─[2:0x7fee142b72a8]
Why is such a huge difference between the two and also why is object.size() doubling the size of y but obj_size doesn't - does it mean the memory allocation has been doubled?
As discussed in r-lib/rlang#678 I recently needed to log what symbols are getting hit in my data_mask using eval_tidy
. @lionel- thought this might be a more appropriate home.
I have prototype using makeActiveBinding
, although Lionel suggested there's a cleaner alternative using objectable.
The protoype is here: https://gist.github.com/cfhammill/4244e29bc667455a2406bf972e4287c6
I'm happy to open this as a PR with the active bindings version, although I'm not sure if/when I would be able to switch this to objectable.
lobstr::ast()
and pryr::ast()
both return an error, when I want to assign a value via =
> lobstr::ast(a = 1)
Error in lobstr::ast(a = 1) : unused argument (a = 1)
> pryr::ast(a = 1)
Error in pryr::ast(a = 1) : unused argument (a = 1)
In contrast the <-
assignment is accepted in both
> lobstr::ast(a <- 1)
X-`<-`
+-a
\-1
> pryr::ast(a <- 1)
\- ()
\- `<-
\- `a
\- 1
Edit: It is probably because a =
implies to look for an argument called a, which can not be found, since x
is the only argument of lobstr::ast()
and hence, the best I can come up with is a workaround involving extra brackets
> lobstr::ast(x = 1)
1
> lobstr::ast(a = 1)
Error in lobstr::ast(a = 1) : unused argument (a = 1)
> lobstr::ast(x = a = 1)
Error: unexpected '=' in "lobstr::ast(x = a ="
> lobstr::ast(x = {a = 1})
X-`{`
\-X-`=`
+-a
\-1
> lobstr::ast(x = (a = 1))
X-`(`
\-X-`=`
+-a
\-1
Example:
obj_size(parent.env(.GlobalEnv), env = emptyenv())
make_type_abrev()
and type_sum()
are inconsistent, and I think neither are correct. If it's a vector (how do we tell?) we should probably use vctrs::type_sum()
(+ vctrs::vec_size()
?) and otherwise use something like R7:::obj_desc()
.
While preparing reprex for someone else, I've created an object with some linear models in a list-column. My goal was to show the size of the object, so I've used lobstr::obj_size()
, but using it kills the R session. pryr::object_size()
works without an issue.
Minimal reprex with session info:
library(magrittr)
models <- tibble::as_tibble(mtcars) %>%
dplyr::group_by(carb) %>%
tidyr::nest() %>%
dplyr::mutate(model = purrr::map(data, ~lm(disp ~ ., data = .x))) %>%
tidyr::unnest(data, .drop = FALSE)
pryr::object_size(models)
#> 90 kB
## this would kill R session
#lobstr::obj_size(models)
Created on 2019-01-04 by the reprex package (v0.2.1)
devtools::session_info()
#> ─ Session info ──────────────────────────────────────────────────────────
#> setting value
#> version R version 3.5.2 (2018-12-20)
#> os Ubuntu 18.04.1 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language en_US
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz Europe/Berlin
#> date 2019-01-04
#>
#> ─ Packages ──────────────────────────────────────────────────────────────
#> package * version date lib source
#> assertthat 0.2.0 2017-04-11 [1] CRAN (R 3.5.0)
#> backports 1.1.3 2018-12-14 [1] CRAN (R 3.5.1)
#> callr 3.1.1 2018-12-21 [1] CRAN (R 3.5.2)
#> cli 1.0.1 2018-09-25 [1] CRAN (R 3.5.1)
#> codetools 0.2-16 2018-12-24 [4] CRAN (R 3.5.2)
#> crayon 1.3.4 2017-09-16 [1] CRAN (R 3.5.1)
#> desc 1.2.0 2018-05-01 [1] CRAN (R 3.5.0)
#> devtools 2.0.1 2018-10-26 [1] CRAN (R 3.5.1)
#> digest 0.6.18 2018-10-10 [1] CRAN (R 3.5.1)
#> dplyr 0.7.99.9000 2018-11-25 [1] local
#> evaluate 0.12 2018-10-09 [1] CRAN (R 3.5.1)
#> fs 1.2.6 2018-08-23 [1] CRAN (R 3.5.1)
#> glue 1.3.0 2018-10-14 [1] Github (tidyverse/glue@4e74901)
#> highr 0.7 2018-06-09 [1] CRAN (R 3.5.0)
#> htmltools 0.3.6 2017-04-28 [1] CRAN (R 3.5.0)
#> knitr 1.21 2018-12-10 [1] CRAN (R 3.5.1)
#> magrittr * 1.5 2014-11-22 [1] CRAN (R 3.5.0)
#> memoise 1.1.0 2017-04-21 [1] CRAN (R 3.5.0)
#> pillar 1.3.1 2018-12-15 [1] CRAN (R 3.5.2)
#> pkgbuild 1.0.2 2018-10-16 [1] CRAN (R 3.5.1)
#> pkgconfig 2.0.2 2018-08-16 [1] CRAN (R 3.5.1)
#> pkgload 1.0.2 2018-10-29 [1] CRAN (R 3.5.1)
#> prettyunits 1.0.2 2015-07-13 [1] CRAN (R 3.5.0)
#> processx 3.2.1 2018-12-05 [1] CRAN (R 3.5.1)
#> pryr 0.1.4 2018-02-18 [1] CRAN (R 3.5.2)
#> ps 1.3.0 2018-12-21 [1] CRAN (R 3.5.2)
#> purrr 0.2.5 2018-05-29 [1] CRAN (R 3.5.0)
#> R6 2.3.0 2018-10-04 [1] CRAN (R 3.5.1)
#> Rcpp 1.0.0 2018-11-07 [1] CRAN (R 3.5.1)
#> remotes 2.0.2 2018-10-30 [1] CRAN (R 3.5.1)
#> rlang 0.3.0.1 2018-10-25 [1] CRAN (R 3.5.1)
#> rmarkdown 1.11 2018-12-08 [1] CRAN (R 3.5.1)
#> rprojroot 1.3-2 2018-01-03 [1] CRAN (R 3.5.0)
#> sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 3.5.1)
#> stringi 1.2.4 2018-07-20 [1] CRAN (R 3.5.1)
#> stringr 1.3.1 2018-05-10 [1] CRAN (R 3.5.0)
#> testthat 2.0.1 2018-10-13 [1] CRAN (R 3.5.1)
#> tibble 1.4.2 2018-01-22 [1] CRAN (R 3.5.0)
#> tidyr 0.8.2 2018-10-28 [1] CRAN (R 3.5.1)
#> tidyselect 0.2.5 2018-10-11 [1] CRAN (R 3.5.1)
#> usethis 1.4.0 2018-08-14 [1] CRAN (R 3.5.1)
#> withr 2.1.2 2018-03-15 [1] CRAN (R 3.5.0)
#> xfun 0.4 2018-10-23 [1] CRAN (R 3.5.1)
#> yaml 2.2.0 2018-07-25 [1] CRAN (R 3.5.0)
#>
#> [1] /home/misha/R/x86_64-pc-linux-gnu-library/3.5
#> [2] /usr/local/lib/R/site-library
#> [3] /usr/lib/R/site-library
#> [4] /usr/lib/R/library
What I noticed is that if I omit last line in the pipeline tidyr::unnest(data, .drop = FALSE)
same problem happens, but it takes ~10 seconds for R session to die. With this line present R session dies immediately.
RStudio info:
Version 1.2.1114
Build 1104 (2e0f7658)
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.10.1 Chrome/61.0.3163.140 Safari/537.36
obj_size()
provides the basic structure for the recursion. The main difference would be that each call returns a nested list containing the current object, and a (potentially named) list of its children. Would want options to control the maximum depth to recurse (so you could explore iteratively, if needed), whether or not to show CHARSXPs, and how to handle ALTREP. By default, would show environments in the same way as lists, rather than exposing the details of their internal hash tables (but needs option to show full details for debugging other code).
Need small S3 class to capture an object — it's address (string), type (string), NAMED (integer?), and id (integer, if seen before, NULL otherwise), and its children (named list). Its print method would take care of generating the tree display.
This would effectively become a replacement for .Internal(inspect(x))
, with a better display (i.e. using colour and unicode tree characters) and displaying a spanning tree (instead of potentially getting stuck in infinite loops). Would replace internal obj_formals()
etc, and altrep()
.
When I typically reach for obj_size
I am using it on relatively large objects (MBs or GBs). I am curious if there is a recommended formatting method for converting from printing as Bytes to KB, MB, GB, etc. I can manually convert with a combination of division + fsprint
, paste0
, round
etc.
There are a few r-lib
packages that provide nice printing of bytes, but as far as I can tell do not have a method for lobstr_bytes
objects. Does it make sense to have prettyunits
operate natively on lobstr_bytes
via a method or even having a function argument inside obj_size()
for unit conversion/prettier printing?
Thank you for your time reviewing. 🖖
library(prettyunits)
library(lobstr)
library(magrittr)
car_size <- obj_size(mtcars)
# lobstr_bytes format
class(car_size)
#> [1] "lobstr_bytes"
car_size_num <- obj_size(mtcars) %>%
as.numeric()
# numeric
class(car_size_num)
#> [1] "numeric"
# scales::number_bytes() is deprecated
# and only works on numeric converted obj_size
scales::number_bytes(car_size)
#> Error in UseMethod("round_any"): no applicable method for 'round_any' applied to an object of class "lobstr_bytes"
scales::number_bytes(as.numeric(car_size))
#> [1] "7 KiB"
scales::number_bytes(unclass(car_size))
#> [1] "7 KiB"
# scales::label_bytes() works for numeric or unclassed objects
# but feels a bit awkward outside of ggplot2
scales::label_bytes()(unclass(car_size))
#> [1] "7 kB"
# prettyunits::pretty_bytes works well
# but again requires numeric or unclassed conversion
prettyunits::pretty_bytes(car_size)
#> Error in as.data.frame.default(x[[i]], optional = TRUE): cannot coerce class '"lobstr_bytes"' to a data.frame
prettyunits::pretty_bytes(unclass(car_size))
#> [1] "7.21 kB"
Created on 2021-08-27 by the reprex package (v2.0.0)
I was using rlang::blast()
, and trying to understand how it works.
lazyeval::ast_()
shows the actual call:
blast <- function(expr, env = caller_env()) {
eval_bare(enexpr(expr), env)
}
exp <- quo(a + b)
f <- function(x) {
lazyeval::ast_(sys.call())
invisible()
}
blast(f(!!exp))
#> ┗ ()
#> ┗ `f
#> ┗ ()
#> ┗ `~
#> ┗ ()
#> ┗ `+
#> ┗ `a
#> ┗ `b
However lobstr::ast(!!x)
unwraps the quosures so you don't see the actual call:
g <- function(x) {
lobstr::ast(!!sys.call())
invisible()
}
blast(g(!!exp))
#> █─g
#> └─█─`+`
#> ├─a
#> └─b
Starting to noodle on this idea because I think it will be useful for the data structures chapter in R4DS
# Atomic vectors ----------------------------------------------------------
# Compactly displays type and length
somethingstr(1:100)
#> int[100]
somethingstr(letters)
#> chr[26]
# Also displays attributes.
# Class gets special handling
somethingstr(factor(letters))
#> int[26] <factor>
#> @ levels: chr[26]
# (I imagine this being used once you've taught basic data structures
# and purrr, so it's useful to see the details, instead the helpful
# lies that str() tells you.)
somethingstr(Sys.time())
#> dbl[1] <POSIXct, POSIXt>
#> @ tzone: chr[1]
# Lists -------------------------------------------------------------------
# Shows hierarchy
x <- list(
list(
1,
2
),
list(
3,
4
)
)
somethingstr(x)
#> list[4]
#> - 1: list[2]
#> - 1: dbl[1]
#> - 2: dbl[1]
#> - 2: list[2]
#> - 1: dbl[1]
#> - 2: dbl[1]
# Very long lists are truncated
x <- replicate(100, list(runif(5)))
somethingstr(x)
#> list[100]
#> - 1: dbl[5]
#> - 2: dbl[5]
#> - 3: dbl[5]
#> - 4: dbl[5]
#> - 5: dbl[5]
#> ...
# So are very deep lists
x <- list()
for (i in 1:100) x$x <- list(x)
somethingstr(x)
#> list[1]
#> 1. list[1]
#> 1. list[1]
#> 1. list[1]
#> 1. ...
# And length and depth interplay in some complicated way. Maybe the way
# to think about it is that you want to (say) print at most 100 lines.
# How should you allocate those lines to best display the structure of
# the object? I don't think simple cut-offs for length vs. depth will
# work in general.
# Think about something() on a data frame containing models etc.
# Maybe can assume unnamed lists are generally homogeneous?
# Names get special treatment
somethingstr(mtcars)
#> list[11] <data.frame>
#> $ mpg : dbl[32]
#> $ cyl : dbl[32]
#> $ disp: dbl[32]
#> $ hp : dbl[32]
#> $ drat: dbl[32]
#> $ wt : dbl[32]
#> $ qsec: dbl[32]
#> $ vs : dbl[32]
#> $ am : dbl[32]
#> $ gear: dbl[32]
#> $ carb: dbl[32]
#> @ row.names: chr[32]
# Very long names get truncted
x <- list(this_is_a_very_very_very_very_long_name = 1:10)
somethingstr(x)
#> list[1]
#> $ this_is_a_very_...: int[10]
# Environments ----------------------------------------------------------------
# Need someway to control recursion into environments. Probably don't
# want it on by default because there are too many objects that have
# (possibly big) environments attached (e.g. formulas)
somethingstr(globalenv())
#> env[2] [R_GlobalEnv]
somethingstr(globalenv(), show_env = 0L)
#> env[2] [R_GlobalEnv]
#> $ df: list[1] <data.frame>
#> $x: int[100]
#> @row.names: int[1]
#> $ i: int[10]
#> @parent.env: env[10] [tools:rstudio]
# show_env = 0L would also show the contents of parent.env.
# Functions ---------------------------------------------------------------
somethingstr(function(x = 1:10, y = x) {})
#> func[2]
#> $x: `1:10
#> $y: `x
#> * env: env[4] [R_GlobalEnv]
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
To print ALTREP objects. The inspect method typically provides more information about the object. E.g.
❯ .Internal(inspect(1:100))
@7fa458bec718 13 INTSXP g0c0 [NAM(7)] 1 : 100 (compact)
❯ lobstr::sxp(1:100)
[1:0x7fa458be6a60] <INTSXP[100]> (altrep named:7)
❯ .Internal(inspect(tl))
@7fa458bec8d8 13 INTSXP g1c0 [MARK,NAM(7)] ALTREP progress::tick_along
@7fa458bec868 13 INTSXP g1c0 [MARK,NAM(7)] 1 : 10000 (compact)
❯ lobstr::sxp(tl)
[1:0x7fa458bec8d8] <INTSXP[10000]> (altrep named:7)
i.e. how should ALTREP be handled?
So you know it's a quosure
ref
method will call as.list.reactiveValues
for shiny reactive values (such as session), which causes errors.
to help explain how mockr/mockery works.
lobstr::obj_size(as.pairlist(1:1E6))
tracemem()
does a better job of telling you when a copy occurs, and the exact meaning of obj_refs()
is likely to experience some churn in the next few years.
library(lobstr)
n <- 1.343E8
largeframe <- data.frame(runif(n),
sample(LETTERS, n, T),
sample(letters, n, T))
largecopy <- largeframe
obj_size(largeframe, largecopy)
obj_sizes(largeframe, largecopy)
Since object_size()
code derived from object.size()
(I'm happy to take a stab at this if it seems useful! cc @filipsch who is interested in this issue)
Really enjoyed the NYC R conference talk on lobstr! This might be outside the scope of lobstr, but it seems like being able to enhance the AST with line / column info could lead to useful ways of allowing people to explore the AST, and its relationship back to their code.
I worked briefly on connecting AST and parse data while flying somewhere, but never finished. I think the key points are...
1 + 2
, the +
is not an expr token)There may be a much easier way to do this. Here's is a comparison of the parse data for a binary operator.
Code used to graph parsed data
# taken from https://github.com/halpo/parser/blob/master/R/plot.parser.R
library(igraph)
plot.parser <- function(x, ...){
y = getParseData(x)
stopifnot(require(igraph))
y$new.id <- seq_along(y$id)
h <- graph.tree(0) + vertices(id = y$id, label= y$text)
for(i in 1:nrow(y)){
if(y[i, 'parent'])
h <- h + edge(c(y[y$id == y[i, 'parent'], 'new.id'], y[i, 'new.id']))
}
plot(h, layout=layout.reingold.tilford, ...)
}
create_parse_graph <- function(pd) {
pd$new.id <- seq_along(pd$id)
h <- graph.tree(0) + vertices(id = pd$id, label= pd$text)
for(i in 1:nrow(pd)){
if(pd[i, 'parent'])
h <- h + edge(c(pd[pd$id == pd[i, 'parent'], 'new.id'], pd[i, 'new.id']))
}
h
}
Some notes on matching nodes
# Steps to map to AST from parse data
# 1. start at root AST node (call ast), and PD node (call pd)
#
# 2a. if is.atomic(ast), build atomic node by returning ast[1]. Otherwise...
# 2b. if is.call(ast) and is.name(ast[[1]]), then ast[[1]] is child token of pd
# i. standard call will make it the first child token
# ii. binary will be in the middle (so easier to search for ast[[1]])
# 2c. if is.call(ast) and is.call(ast[[1]]), then it is first child of pd
#
# 3. Get all child exprs of pd (in order), move one matching ast[[1]] to front
#
# 4. You have matched up ast to pd! Recurse
Prepare for release:
rhub::check_for_cran()
rhub::check(platform = "solaris-x86-patched")
rhub::check(platform = "ubuntu-rchk")
devtools::check_win_devel()
Perform release:
devtools::check_win_devel()
(again!)devtools::submit_cran()
Wait for CRAN...
Template from r-lib/usethis#338
for ALTREP
test_that("size of S4 objects same as base", {
Z <- methods::setClass("Z", slots = c(x = "integer"))
z <- Z(x = 1L)
expect_same(z)
})
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.