Skip to content

Improve global env and knitr unwind #194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 24, 2022
Merged

Improve global env and knitr unwind #194

merged 3 commits into from
Feb 24, 2022

Conversation

lionel-
Copy link
Member

@lionel- lionel- commented Feb 23, 2022

Closes #136
Follow-up to #187

  • Consistently use session scope inside knitr, no matter the evaluation environment.
  • Do not use session scope with non-top-level evaluations in the global environment.

@lionel- lionel- requested review from hadley and jennybc February 23, 2022 19:14
Copy link
Member

@jennybc jennybc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I made a few small suggestions.

I test drove this a bit and everything feels right.

Something that doesn't work the way you might expect (but also didn't work before) is this:

If you render foo.Rmd with rmarkdown::render("foo.Rmd") in your current R session, any defer()ed events remain deferred after the render. Which makes sense and yet feels semi-wrong. You can clear them with withr::deferred_clear() or run them with withr::deferred_run() or by restarting R. I'm just bringing this up to plant the idea that maybe one day we'd want a way to express that events scheduled during the course of rendering an .Rmd should be executed "when this render is done". Basically, a notion of .Rmd scope or file scope, I suppose. The obvious / low-tech way to do this is to simply insert a concluding chunk that contains withr::deferred_run().

But I definitely don't want to clog up this PR with a new matter. It's just something I thought about while testing this.

Co-authored-by: Jennifer (Jenny) Bryan <jenny.f.bryan@gmail.com>
@lionel-
Copy link
Member Author

lionel- commented Feb 24, 2022

If you render foo.Rmd with rmarkdown::render("foo.Rmd") in your current R session, any defer()ed events remain deferred after the render. Which makes sense and yet feels semi-wrong.

I agree. Also in notebooks, rendering chunks causes the deferred expressions to pile up in the session. I think the knitr support as it stands in this PR should mostly be regarded as a stopgap.

To implement chunk scope or document scope, we'd need a redesign of evaluate to use eval_bare() instead of eval() when looping over the lines of a chunk, as well as a modification to knitr. Hadley told me yesterday this wouldn't be worth it.

Worth noting that the "document scope" that you propose would devolve to "chunk scope" when knitting a single chunk in a notebook, IIUC. This seems to make sense.

Also I realised yesterday that in document-generation environments such as roxygen2, we can make something like this work easily, without any changes to the rmd stack:

local_foo(.frame = my_scope())

I look forward to being able to clean up state in Rmd docs using a similar pattern. Though IIRC @gaborcsardi told me this might not be straightforward because of the way Rmd pieces are assembled from multiple locations.

@lionel- lionel- merged commit fbd8f03 into main Feb 24, 2022
@lionel- lionel- deleted the top-level-global branch February 24, 2022 08:11
@hadley
Copy link
Member

hadley commented Feb 24, 2022

Won't you get the same problem as source()ing a file that uses local_*() at the top-level?

Would it be possible to look in the call stack for specific calls (like source() or render()) and attach the cleanup to that frame?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Issues with handlers attribute
3 participants