You're conflating 3 different things here: how methods are selected, how R treats missing arguments, and how the standardGeneric() call is implemented.
Maybe more relevant, if this question is motivated by a practical need, you may want to rethink what the generic function does. "Nonstandard" generic functions are called that for a reason. The concept behind methods in S is that a generic function defines the _function_ or purpose of the computation, but it's only the methods that define how the purpose is carried out. Using a nonstandard generic that does some extra computation always blurs the concept, and often makes methods harder to write or understand. That you've found it necessary to worry about the subtle points in your question is a warning sign. It's usually worth asking whether the place that you call standardGeneric() could in fact _be_ the generic, with the other computations moved to a nongeneric wrapper function. Having said that, when the computations depend on missing arguments, the situation may be more complicated. Anyway, the following relate to your question. 1. In method selection, the "missing" class is used if the C-level equivalent of the test missing(ARG) is TRUE when selection takes place. On to point 2. 2. The R evaluator stores a special object corresponding to missing arguments. Missing arguments are treated by the lazy evaluation rules, so the exact contents of the current object of this name in the local environment will depend on whether there has been a reference to the argument. The missing(ARG) test remains TRUE when the default expression is evaluated but becomes FALSE if a direct assignment of ARG takes place (just reporting this, not defending it). 3. standardGeneric() creates a new context into which it copies bindings for all the objects in the frame of the generic function call, but tries to maintain defaults for missing arguments. If you want to see how it works, look at the routine R_execMethod in file src/main/eval.c of the R source. The somewhat unfortunate result of all this can be seen by comparing two nonstandard generics: setGeneric("foo", function(x, y){if(missing(y)) y <- x+1; standardGeneric("foo")}) setGeneric("foo2", function(x, y = x+1){if(missing(y)) message(y); standardGeneric("foo2")}) The "foo" function will never dispatch a method for c("numeric", "missing") because y is assigned directly. The "foo2" function will dispatch such a method though, even though the numerical value of y will be the same in message(y). As may be obvious, the computation is subtle and it might be foolish to rely on the details as if they were part of the API. Parlamis Franklin wrote: > i believe the following is true but would appreciate confirmation > that it is intended behavior and will continue: > > if a default argument is employed in the definition of a generic > function, and the generic is called with the argument in question > (call it 'ARG') missing, then the method for signature (..., ARG = > "missing", ...) will be called by 'standardGeneric' whether or not > ARG is evaluated in the body of the generic prior to the call to > 'standardGeneric'; however, the value assigned to ARG in the method > call will depend on whether ARG was evaluated in the body of the > generic prior to the call to 'standardGeneric' (with the default > value assigned in the case of prior evaluation and no value assigned > in the case of no prior evaluation). furthermore, if ARG is > explicitly assigned to in the body of the generic prior to the call > to 'standardGeneric', then the method for signature (..., ARG = class > (ARG), ...) will be called, with the assigned value of ARG passed to > the call. > > this behavior is exhibited by the code below: > > __ > > setGeneric("foo", function(x = 1) standardGeneric("foo"), > useAsDefault = FALSE) > setMethod("foo", signature(x = "missing"), function(x = 3) x) > > setGeneric("foo2", function(x = 1) {x; standardGeneric("foo2")}, > useAsDefault = FALSE) > setMethod("foo2", signature(x = "missing"), function(x = 3) x) > > setGeneric("foo3", function(x = 1) {x<-2; standardGeneric("foo3")}, > useAsDefault = FALSE) > setMethod("foo3", signature(x = "missing"), function(x = 3) x) > setMethod("foo3", signature(x = "numeric"), function(x = 3) x^2) > > foo() # returns 3 > foo2() # returns 1 > foo3() # returns 4 > > ___ > > franklin parlamis > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel