[R-pkg-devel] NOTE about use of `:::`

David Kepplinger d@v|d@kepp||nger @end|ng |rom gm@||@com
Mon Dec 19 19:58:41 CET 2022


I think I will go with the suggestion of creating a new empty environment,
adding only the argument parsing function. Moreover I will use the same
name as the user-facing function that's being invoked,  i.e.,

foo <- function(...) {
   call <- match.call(expand.dots = TRUE)
   call[[1]] <- quote(parse_args)
   envir <- new.env(parent = parent.frame())
   envir$foo <- parse_args

   eval(call, envir)
}

This way a trace-back shows the function the user expects, without having
to export the parsing function or duplicate the code in the user-facing
functions.

Thanks again everyone for the suggestions.

All the best,
David


On Thu, Dec 15, 2022 at 4:39 AM Duncan Murdoch <murdoch.duncan using gmail.com>
wrote:

> If you want the name of the function to appear, then you can put the
> function in an environment whose parent is where most of the evaluation
> should take place.  For example,
>
> f <- function(...) {
>    call <- match.call(expand.dots = TRUE)
>    call[[1]] <- quote(parse_args)
>    envir <- new.env(parent = parent.frame())
>    envir$parse_args <- parse_args
>
>    eval(call, envir)
> }
>
> parse_args <- function(...) {
>    cat("args were ", names(list(...)), "\n")
>    stop("Error in parse_args")
> }
>
> f(a = 1, b = 2)
> #> args were  a b
> #> Error in parse_args(a = 1, b = 2): Error in parse_args
>
> Duncan Murdoch
>
>
> On 14/12/2022 8:35 p.m., David Kepplinger wrote:
> > Thank you both for the suggestions. I would prefer a clean stack trace in
> > case of errors as input errors are caught by this function and hence
> users
> > might very well see errors emitted from it. It seems more informative to
> me
> > if the error message would say "Error in .parse_args…" than "Error in
> > new.env(…". But since this solution was suggested by both of you it is
> > likely that CRAN too would demand this or a similar approach instead of
> > using `:::`. I know `:::` is expansive, but the computations that follow
> > are typically at least a few minutes so anything that takes less than a
> few
> > seconds won't be noticeable.
> >
> > I also thought about using `...` before, but then the signature of the
> > user-facing functions would be incomplete and IDEs won't be able to
> provide
> > suggestions.
> >
> > Thanks for the help!
> >
> > -- David
> >
> > On Wed, Dec 14, 2022 at 7:11 PM Simon Urbanek <
> simon.urbanek using r-project.org>
> > wrote:
> >
> >> David,
> >>
> >> why not
> >>
> >> call[[1]] <- parse_args
> >>
> >> The assignment is evaluated in your namespace so that makes sure the
> call
> >> is that of your function. The only downside I see is that in a stack
> trace
> >> you'll see the definition instead of the name.
> >> Or possibly
> >>
> >> do.call(parse_args, as.list(call[-1]))
> >>
> >> Cheers,
> >> Simon
> >>
> >> PS: Note that ::: is expensive - it probably doesn't matter here, but
> >> would in repeatedly called functions.
> >>
> >>
> >>> On 15/12/2022, at 12:19 PM, David Kepplinger <
> david.kepplinger using gmail.com>
> >> wrote:
> >>>
> >>> Dear List,
> >>>
> >>> I am working on updating the pense package and refactored some of the
> >>> methods. I have several functions which take the same arguments, hence
> >> I'm
> >>> sending all these arguments to an internal function, called
> >> `parse_args()`.
> >>> Since I want to evaluate the arguments in the caller's environment, I'm
> >>> using the following code
> >>>
> >>>   call <- match.call(expand.dots = TRUE)
> >>>   call[[1]] <- quote(pense:::parse_args)
> >>>   args <- eval.parent(call)
> >>>
> >>> Of course, R CMD CHECK complains about the use of `:::`, as it's almost
> >>> never needed. I think the above usage would fall into that area of
> >>> "almost", but I'm not sure if (a) there's a better approach and (b) the
> >>> CRAN team would agree with me. I would have to test (b) by submitting
> and
> >>> working with the CRAN team, but I wanted to ask the list first to see
> if
> >>> I'm missing something obvious. I don't want to export the function
> >>> parse_args() as it's not useful for a user, and the use is truly
> >> internal.
> >>>
> >>> Thanks and all the best,
> >>> David
> >>>
> >>>        [[alternative HTML version deleted]]
> >>>
> >>> ______________________________________________
> >>> R-package-devel using r-project.org mailing list
> >>> https://stat.ethz.ch/mailman/listinfo/r-package-devel
> >>>
> >>
> >>
> >
> >       [[alternative HTML version deleted]]
> >
> > ______________________________________________
> > R-package-devel using r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-package-devel
>
>

	[[alternative HTML version deleted]]



More information about the R-package-devel mailing list