Это ... "ожидаемое поведение".Я говорю это, потому что считаю, что это технически верно, но, вероятно, у пользователя нет возможности ожидать этого обязательно.Если вас не волнует, почему это происходит, но вы просто хотите посмотреть, как это обойти, перейдите к заголовку «Исправление», потому что в следующем объяснении ошибки мало что есть.
Чтоозначает 'function' is not a function, but of type 8
?
type 8
относится к типу 8 SEXP
.Из Раздела первого Руководства по внутренним компонентам R :
То, что пользователи R считают переменными или объектами, - это символы, которые связаны со значением.Значение можно рассматривать как SEXP (указатель) или структуру, на которую оно указывает, SEXPREC ...
В настоящее время используются SEXPTYPE 0:10 и 13:25 ....
нет SEXPTYPE Описание
...
3 замыкания CLOSXP
...
8 Встроенные функции BUILTINSXP
NextMethod()
ожидает CLOSXP
не BUILTINSXP
.Мы можем увидеть это, если посмотрим на исходный код (около строки 717) do_nextmethod()
, функцию C, лежащую в основе NextMethod()
SEXP attribute_hidden do_nextmethod(SEXP call, SEXP op, SEXP args, SEXP env)
{
// Some code omitted
if (TYPEOF(s) != CLOSXP){ /* R_LookupMethod looked for a function */
if (s == R_UnboundValue)
error(_("no calling generic was found: was a method called directly?"));
else
errorcall(R_NilValue,
_("'function' is not a function, but of type %d"),
TYPEOF(s));
}
Так почему это произошло здесь?Вот где это становится сложно.Я полагаю, это потому, что, передавая NextMethod()
через capture.output()
, он вызывается с помощью eval()
, который является встроенным (см. builtins()
).
Так как мы можем справиться с этим?Читайте дальше ...
Исправление
Мы можем смоделировать вывод захвата с умным использованием sink()
, cat()
и tempfile()
:
foo.baz <- function(x, ...) {
# Create a temporary file to store the output
tmp <- tempfile("tmp.txt")
# start sink()
sink(tmp)
# call NextMethod() just for the purpose of capturing output
NextMethod()
# stop sink'ing
sink()
# store the output in an R object
y <- readLines(tmp)
# here we'll cat() the output to make sure it worked
cat("The output was:", y, "\n")
# destroy the temporary file
unlink(tmp)
# and call NextMethod for its actual execution
NextMethod()
}
foo(structure(1, class = c("baz", "bar")))
# 1