2015-01-09 4 views
8

Если вы определяете переменную внутри общей функции, она доступна для метода. Например:Область применения общих функций R

g <- function(x) { 
    y <- 2 
    UseMethod("g") 
} 
g.default <- function() y 
g() 
[1] 2 

Но если переменная, которую вы определяете, имеет то же имя, что и параметр функции, этого не происходит. Кажется, что R удаляет эту переменную перед вызовом метода:

g <- function(x) { 
    x <- 2 
    UseMethod("g") 
} 
g.default <- function() x 
g() 
Error in g.default() : object 'x' not found 

Может кто-нибудь объяснить, что здесь происходит?

ответ

4

Следующие комментарии от C source file that defines do_usemethod хотя бы намекают на то, что происходит. См. Особенно второе предложение второго перечисленного элемента.

В принципе, это выглядит (из-за немого применения правила в этой второй точке), значение x не копируется, потому что код C проверяет, является ли он среди формалей, видит, что он есть, и поэтому исключает, если из списка переменных, вставленных в среду оценки метода.

/* usemethod - calling functions need to evaluate the object 
* (== 2nd argument). They also need to ensure that the 
* argument list is set up in the correct manner. 
* 
* 1. find the context for the calling function (i.e. the generic) 
* this gives us the unevaluated arguments for the original call 
* 
* 2. create an environment for evaluating the method and insert 
* a handful of variables (.Generic, .Class and .Method) into 
* that environment. Also copy any variables in the env of the 
* generic that are not formal (or actual) arguments. 
* 
* 3. fix up the argument list; it should be the arguments to the 
* generic matched to the formals of the method to be invoked */ 
+0

Я согласен, что именно поэтому это происходит. Но чтобы «обойти» это, если вы хотите изменить объект, который вы отправляете в общий, вы должны передать его как второй параметр в 'UseMethod()'. Кроме того, было бы неплохо, если бы в общих реализациях по крайней мере был общий общий аргумент. Странно, что 'g.default()' не имеет параметра. Вот где можно было бы ожидать изменения «x». – MrFlick

+0

@MrFlick. Но, как вы можете видеть, даже этот второй аргумент 'UseMethod' не передается. Он используется только для определения того, какой метод следует отправлять (что в любом случае похоже на то, что вам нужно от вашего общего вызова функции). Я согласен с вашей общей рекомендацией о том, как структурировать списки аргументов нескольких методов. –

+0

@MrFlick - я должен признать, что до сих пор я не оценил, что вы * можете *, если хотите, использовать 'UseMethod()' для отправки на основе значений нескольких разных аргументов (подробнее как то, что происходит с классами S4). Это потребует немного или предварительной обработки в теле общего типа, но похоже, что этого было бы не слишком сложно. Интересно, используется ли это в каких-либо известных R-пакетах. –

Смежные вопросы