NextMethod() and argument laziness

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

NextMethod() and argument laziness

Davis Vaughan
Hi all, I'd like to ask if the following behavior is a bug. To me it
certainly feels surprising, at the very least. In this example, I would
like to call NextMethod() from my `child` object, have `cols` be left
untouched, and then substitute(cols) in the parent method. It works when
you use a `parent` object (as expected), but I would have also expected to
get `mpg` back when calling it from the `child` method.

my_generic <- function(x, cols) {
  UseMethod("my_generic")
}
my_generic.parent <- function(x, cols) {
  substitute(cols)
}
my_generic.child <- function(x, cols) {
  NextMethod()
}
obj_parent <- structure(mtcars, class = c("parent", class(mtcars)))
obj_child <- structure(obj_parent, class = c("child", class(obj_parent)))

my_generic(obj_parent, mpg)
#> mpg

my_generic(obj_child, mpg)
#> cols

Thanks,
Davis

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: NextMethod() and argument laziness

Tomas Kalibera

On 8/7/19 3:10 PM, Davis Vaughan wrote:

> Hi all, I'd like to ask if the following behavior is a bug. To me it
> certainly feels surprising, at the very least. In this example, I would
> like to call NextMethod() from my `child` object, have `cols` be left
> untouched, and then substitute(cols) in the parent method. It works when
> you use a `parent` object (as expected), but I would have also expected to
> get `mpg` back when calling it from the `child` method.
>
> my_generic <- function(x, cols) {
>    UseMethod("my_generic")
> }
> my_generic.parent <- function(x, cols) {
>    substitute(cols)
> }
> my_generic.child <- function(x, cols) {
>    NextMethod()
> }
> obj_parent <- structure(mtcars, class = c("parent", class(mtcars)))
> obj_child <- structure(obj_parent, class = c("child", class(obj_parent)))
>
> my_generic(obj_parent, mpg)
> #> mpg
>
> my_generic(obj_child, mpg)
> #> cols

This works as documented, see ?NextMethod:

"the arguments will be the same in number, order and name as those to
the current method but their values will be promises to evaluate their
name in the current method and environment"

Hence NextMethod needs to create a promise with a name matching the
formal argument name of the function from which NextMethod is invoked.
Note this is not the same as with UseMethod, and this is also why
substitute() works differently with UseMethod.

Best
Tomas

>
> Thanks,
> Davis
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel