Skip to content
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

Recursive evaluate #36

Closed
jeroen opened this issue May 28, 2013 · 7 comments
Closed

Recursive evaluate #36

jeroen opened this issue May 28, 2013 · 7 comments

Comments

@jeroen
Copy link
Member

jeroen commented May 28, 2013

I am experiencing some strange problems with knitr inside opencpu sometimes which I suspect might be a side effect of the recursive use of evaluate (both by knitr and by opencpu). E.g. a toy example:

evaluate(quote(evaluate(quote(plot(iris))))

Which parts of evaluate might be sensitive to recursion problem? I am mostly thinking about the plot hooks, but perhaps other things as well? @yihui, have you ever experienced problems when trying to call knit inside evaluate, i.e. evaluate("knit(...)")?

@yihui
Copy link
Collaborator

yihui commented May 28, 2013

I have never called evaluate that way, so I do not know.

@kforner
Copy link

kforner commented Jul 31, 2014

Hi,
I stumbled on that issue tracking a a bug with knit_child, doing plot in a for loop: basically only the last plot was produced.

The problem is due to the recursive evaluate calls: first call by knit() for the R chunk on the parent document (issuing a knit_child), and the second call by the knit child, calling knit then evaluate again.
I realized that some (plot) hooks installed by the first evaluate were running during the second evaluate call.
So the fix is quite simple: change the default argument of evaluate:::set_hooks to "replace" instead of "append". But there will be side-effects.

What I humbly suggest would be:

  1. to add an option to evaluate (e.g. replace_hooks = FALSE), forwarded to evaluate_call, then used for the set_hooks call.
  2. to modify knitr:::block_exec() so that when child_mode is TRUE, call evaluate with replace_hooks = TRUE

What do you think ?

P.S
About the knit_child bug, note that if you do not put the plot statements in a block (e.g. a if, for or {}) it works, because evaluate is called on each separate statement, because of the parse() results

In the meantime I setup a fix that automatically patches evaluate:::set_hooks when in a knit_child.

@jeroen
Copy link
Member Author

jeroen commented Jul 31, 2014

Somewhat related: a while back I suggested to Paul Murrell that graphic events should better be implemented as conditions rather than hooks. That way we can use the standard withCallingHandlers mechanics to catch the graphic, and pass the recorded plot object directly as an argument to the handler. The advantage of conditions over global hooks is that it supports nested evaluations which are currently problematic.

withCallingHandlers(plot(cars), grid.newpage = function(myplot){
   #deal with recordedPlot object here
})

He seemed open to the idea, but not sure how hard it would be to implement this.

@yihui
Copy link
Collaborator

yihui commented Aug 2, 2014

@kforner That sounds good. Do you mind submitting two pull requests to this repo and the knitr repo, respectively? Thanks!

@kforner
Copy link

kforner commented Aug 19, 2014

Hmm in fact it is more complex that I anticipated, it is difficult to cover all use cases.
But I could fix the knitr use case directly in knitr without modifying evaluate.
The only change that maybe useful would be to export evaluate:::set_hooks.

@kforner
Copy link

kforner commented Sep 2, 2014

As for the knit_child bug, last commit (ba0efa5) by Yihuie seems to fix the problem.

@hadley
Copy link
Member

hadley commented Jun 14, 2024

Closing, since it's been ~10 years (😱) without further discussion.

@hadley hadley closed this as completed Jun 14, 2024
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

No branches or pull requests

4 participants