Thank you Ivan,

Yes I meant `panel.first`.
I fumbled the title and the examples, but the end result is the same:

```
# Works
with(mtcars, plot(wt, mpg, panel.first = {
    arrows(3, 15, 4, 30)
}))

# Doesn't work
plot(mpg ~ wt, data = mtcars, panel.first = {
    arrows(3, 15, 4, 30)
})

```

I saw the bug reported 13 years ago after-the-fact, and the paragraph I missed 
for the manual entry.
Thanks for clarifying both.

I do think making these arguments lazy evaluate would be a welcome change. It's 
especially confusing for new R users trying to use base graphics to plot their 
linear model. But I also understand this would be low priority as user 
workaround is simple (don't use the formula method), and because of the testing 
effort that would be required.

Maybe a warning would be nice, telling users that `panel.first` and 
`panel.last` are evaluated before plotting. I think users would check `?plot` 
before `?plot.formula` and would not see any reason not to try and pass these 
arguments.

Kind Regards,
Erez

On Sat, Jul 6, 2024, at 5:24 PM, Ivan Krylov wrote:
> В Fri, 05 Jul 2024 14:35:40 +0300
> "Erez Shomron" <r-ma...@erezsh.org> пишет:
> 
> > This works as expected:
> 
> > with(mtcars, plot(wt, mpg, plot.first = {
> >     plot.window(range(wt), range(mpg))
> >     arrows(3, 15, 4, 30)
> > }))
> 
> I think you meant panel.first, not plot.first. At least I cannot find
> any mention of plot.first in the R source code. In this example,
> plot.first ends up being an argument of an internal call from
> plot.default() to plot.window(), which evaluates its ellipsis
> arguments. If your plot.first expression returned a non-NULL value, you
> would also have received a warning:
> 
> plot.window(0:1, 0:1, plot.first = message('hello'))
> # hello
> plot.window(0:1, 0:1, plot.first = 123)
> # Warning message:
> # In plot.window(0:1, 0:1, plot.first = 123) :
> #   "plot.first" is not a graphical parameter
> 
> It is indeed documented that "passing [panel.first] from other ‘plot’
> methods may well not work since it may be evaluated too early". The
> plot.formula method deliberately evaluates the arguments in the
> ellipsis, and the workaround suggested in
> https://bugs.r-project.org/show_bug.cgi?id=14591 doesn't help because
> the expression is then evaluated in an undesired environment (parent
> frame, not data).
> 
> You are correct that plot.formula tries to evaluate all its remaining
> arguments in the context of the data passed to the method. In order for
> the lazy evaluation to work, plot.formula would have to (1) know and
> skip all such arguments by name on line 6, minding partial matching, (2)
> rewrite them into the form evalq(original_argument_expression,
> model_frame, parent_frame) so that they would be able to access both
> the data and the variables visible in the frame of the caller, and (3)
> give these expressions to do.call() in place of the original ones.
> 
> (1) sounds especially brittle since plot.formula() may dispatch to
> other plot.* methods. Additionally, great care will need to be taken
> not to break existing code that calls plot.formula, even if it's
> already full of workarounds for plot.formula's behaviour.
> 
> -- 
> Best regards,
> Ivan
> 

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to