https://github.com/moodymudskipper/elephant
make variables remember their history
https://github.com/moodymudskipper/elephant
Last synced: 2 days ago
JSON representation
make variables remember their history
- Host: GitHub
- URL: https://github.com/moodymudskipper/elephant
- Owner: moodymudskipper
- Created: 2020-06-01T00:15:43.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2020-06-02T13:19:19.000Z (almost 5 years ago)
- Last Synced: 2025-04-12T20:52:10.720Z (2 days ago)
- Language: R
- Size: 52.7 KB
- Stars: 15
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.Rmd
Awesome Lists containing this project
- jimsghstars - moodymudskipper/elephant - make variables remember their history (R)
README
---
output: github_document
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```# elephant
> Elephants never forget!
*elephant* is a quick experiment on how to make variables remember their
history.Use `:=` to record a call.
## Installation
Install with:
``` r
remotes::install_github("moodymudskipper/elephant")
```## Example
```{r example}
library(elephant)
```We build an elephant object by using `:=`
```{r}
x := 1
y := 3
z := x + y
x := x * 2
bar <- x + y + z
foo := x + sqrt(z) + barx
y
z
bar
foo
```Here we see `bar` is not an elephant object because it doesn't use `:=` and
`+.elephant` doesn't preserve class and attributes.However `baz <- x` would just copy the object, so in this case it's advised to do
either `baz := x` or `baz <- forget(x)````{r}
# not good
baz <- x
baz# good
baz := x
baz# good
baz <- forget(x)
baz
```We can access the variables used to compute our elephant object by using
`list_calves()` or `calf()`.```{r}
list_calves(foo)
list_calves(foo, "z")
calf(foo, "z")
calf(foo, "z", "x")
```## Debugging with *elephant*
If an elephant calls fails, its memory is preserved and can be recovered using
`poach()`, see the example below :```{r, error = TRUE}
test <- function(){
x := 1
y := 3
z := x * 2
bar <- x + y + z
foo := x + sqrt(z) + bar * letters # <- problematic call!
}test()
poach()
# extract the bar variable as used by foo, for further investigation
foo_poached <- poach()
calf(foo_poached, "letters")# we can go deeper
calf(foo_poached, "z", "x")
```## Benchmark
`:=` has a small overhead, it shouldn't slow your code much most of the time:
```{r}
bench::mark(
elephant_assignment = (foo := x + sqrt(z) + bar),
standard_assignment = (foo <- x + sqrt(z) + bar),
check = FALSE)
```However it wouldn't not be well advised, nor really that useful, to use it in
a loop growing an object as below.```{r}
x := 1
for (i in 1:4) {
x:= x + 1
}
x
```It's especially true for bigger objects as we'd be keeping in memory all previous values
that would have been flushed by the garbage collector if we hadn't used *elephant*.