meta programming - want to refer to users name for object in print method

Hi there!

I'd like to be able to refer to the name of the object that the user has created, in a print method.

Here's a small example, I've got two functions - one of them when I call it on the base data set airquality, which works when I call the function, my_info directly, but when I call my_info inside of another function I lose reference to that name.

I get the sense that I might need to try and do deparse(substitute()) or some variant but specifying the original environment? Or perhaps I need to pass in the environment along with x - I'm just not sure!

If anyone has any thoughts/ideas, I'd love to hear them :slight_smile:

Cheers!

my_info <- function(x){
  obj_name <- deparse(substitute(x))
  cli::cli_alert_info("Access column names with {obj_name}$<var>")
  cli::cli_alert_info("e.g., {obj_name}${names(x)[1]}")
}

my_print <- function(x){
  cli::cli_h1("My Object")
  cli::cli_text("My dims are {dim(x)}")
  my_info(x)
}

# this prints "airquality"
my_info(airquality)
#> ℹ Access column names with airquality$<var>
#> ℹ e.g., airquality$Ozone

# this doesn't print "airquality"
my_print(airquality)
#> 
#> ── My Object ───────────────────────────────────────────────────────────────────
#> My dims are 153 and 6
#> ℹ Access column names with x$<var>
#> ℹ e.g., x$Ozone

Created on 2022-12-22 with reprex v2.0.2

Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.2.1 (2022-06-23)
#>  os       macOS Monterey 12.3.1
#>  system   aarch64, darwin20
#>  ui       X11
#>  language (EN)
#>  collate  en_US.UTF-8
#>  ctype    en_US.UTF-8
#>  tz       Australia/Brisbane
#>  date     2022-12-22
#>  pandoc   2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version date (UTC) lib source
#>  cli           3.4.1   2022-09-23 [1] CRAN (R 4.2.0)
#>  digest        0.6.30  2022-10-18 [1] CRAN (R 4.2.0)
#>  evaluate      0.18    2022-11-07 [1] CRAN (R 4.2.0)
#>  fastmap       1.1.0   2021-01-25 [1] CRAN (R 4.2.0)
#>  fs            1.5.2   2021-12-08 [1] CRAN (R 4.2.0)
#>  glue          1.6.2   2022-02-24 [1] CRAN (R 4.2.0)
#>  highr         0.9     2021-04-16 [1] CRAN (R 4.2.0)
#>  htmltools     0.5.3   2022-07-18 [1] CRAN (R 4.2.0)
#>  knitr         1.41    2022-11-18 [1] CRAN (R 4.2.0)
#>  lifecycle     1.0.3   2022-10-07 [1] CRAN (R 4.2.0)
#>  magrittr      2.0.3   2022-03-30 [1] CRAN (R 4.2.0)
#>  purrr         0.3.5   2022-10-06 [1] CRAN (R 4.2.0)
#>  R.cache       0.16.0  2022-07-21 [1] CRAN (R 4.2.0)
#>  R.methodsS3   1.8.2   2022-06-13 [1] CRAN (R 4.2.0)
#>  R.oo          1.25.0  2022-06-12 [1] CRAN (R 4.2.0)
#>  R.utils       2.12.2  2022-11-11 [1] CRAN (R 4.2.0)
#>  reprex        2.0.2   2022-08-17 [1] CRAN (R 4.2.0)
#>  rlang         1.0.6   2022-09-24 [1] CRAN (R 4.2.0)
#>  rmarkdown     2.18    2022-11-09 [1] CRAN (R 4.2.0)
#>  rstudioapi    0.14    2022-08-22 [1] CRAN (R 4.2.0)
#>  sessioninfo   1.2.2   2021-12-06 [1] CRAN (R 4.2.0)
#>  stringi       1.7.8   2022-07-11 [1] CRAN (R 4.2.0)
#>  stringr       1.5.0   2022-12-02 [1] CRAN (R 4.2.0)
#>  styler        1.8.1   2022-11-07 [1] CRAN (R 4.2.0)
#>  vctrs         0.5.1   2022-11-16 [1] CRAN (R 4.2.0)
#>  withr         2.5.0   2022-03-03 [1] CRAN (R 4.2.0)
#>  xfun          0.35    2022-11-16 [1] CRAN (R 4.2.0)
#>  yaml          2.3.6   2022-10-18 [1] CRAN (R 4.2.0)
#> 
#>  [1] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────
1 Like

seems to work :person_shrugging:

my_info <- function(x){
  obj_name <- deparse(substitute(x))
  cli::cli_alert_info("Access column names with {obj_name}$<var>")
  cli::cli_alert_info("e.g., {obj_name}${names(x)[1]}")
}

my_print <- function(x){
  obj_name <- deparse(substitute(x))
  cli::cli_h1("My Object")
  cli::cli_text("My dims are {dim(x)}")
  eval(parse(text=cli:::glue("my_info({obj_name})")))
}

my_info(airquality)
my_print(airquality)

You can pass an environment to substitute from which it will pull. For the function to work as intended when it is not called in a nested function we set it to the current env. In nested functions you just pass the current (parent for the function) env. :+1:

library(cli)
my_info <- function(x, env = environment()){
  obj_name <- deparse(substitute(x, env))
  cli::cli_alert_info("Access column names with {obj_name}$<var>")
  cli::cli_alert_info("e.g., {obj_name}${names(x)[1]}")
}

my_print <- function(x){
  cli::cli_h1("My Object")
  cli::cli_text("My dims are {dim(x)}")
  my_info(x, environment())
}

my_info(airquality)
#> ℹ Access column names with airquality$<var>
#> ℹ e.g., airquality$Ozone

my_print(airquality)
#> 
#> ── My Object ───────────────────────────────────────────────────────────────────
#> My dims are 153 and 6
#> ℹ Access column names with airquality$<var>
#> ℹ e.g., airquality$Ozone
4 Likes

This is much better than my hack :smiley:

This is just fantastic! Thank you very much, @assignUser !!! :slight_smile:

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.