Вот мой код R. Функции определены как:
f <- function(x, T) {
10 * sin(0.3 * x) * sin(1.3 * x ^ 2) + 0.001 * x ^ 3 + 0.2 * x + 80
}
g <- function(x, T, f=f) {
exp(-f(x) / T)
}
test <- function(g=g, T=1) {
g(1, T)
}
Текущая ошибка:
> test ()
Ошибка в test ():
обещание уже оценивается: рекурсивная ссылка на аргумент по умолчанию или более ранние проблемы?
Если я заменяю определение f
в том , что из g
, то ошибка уходит.
Мне было интересно, в чем была ошибка? Как это исправить , если не подменять определение f
в том , что из g
? Благодарность!
Обновить:
Благодарность! Два вопроса:
(1) если функция test
дополнительно принимает аргумент для f
, вы добавите что-нибудь вроде test <- function(g.=g, T=1, f..=f){ g.(1,T, f.=f..) }
? В случаях с большим количеством рекурсий это хорошая и безопасная практика . ?
(2) если f
это аргумент, не являющийся функцией, например, g <- function(x, T, f=f){ exp(-f*x/T) }
и test <- function(g.=g, T=1, f=f){ g.(1,T, f=f.) }
будет ли использование одного и того же имени как для формальных, так и для фактических нефункциональных аргументов хорошей и безопасной практикой, или это может вызвать некоторые потенциальные проблемы?
.....cumbersome
. :)...
или список для передачи аргументов вниз по цепочке функций. Это намного более гибко (как хорошо, так и плохо), чем все предопределить. Возможно, вам просто понадобится добавить несколько проверок, чтобы убедиться, что ваши исходные аргументы в многоточиях (или в списке) разумны.get("f", envir = parent.frame())
.Если вы укажете контекст оценки аргумента, вы избежите проблемы с тем же именем:
f <- function(x) { 10 * sin(0.3 * x) * sin(1.3 * x ^ 2) + 0.001 * x ^ 3 + 0.2 * x + 80 } g <- function(x, t=1, f=parent.frame()$f) { exp(-f(x) / t) } test <- function(g=parent.frame()$g, t=1) { g(1,t) } test() [1] 8.560335e-37
источник
Как уже упоминалось, проблема возникает из-за того, что аргумент функции определен сам по себе. Однако я хочу добавить объяснение, почему это проблема, потому что понимание, которое привело меня к более легкому (для меня) способу избежать проблемы: просто укажите аргумент в вызове вместо определения.
Это не работает:
x = 4 my.function <- function(x = x){} my.function() # recursive error!
но это работает:
x = 4 my.function <- function(x){} my.function(x = x) # works fine!
Аргументы функции существуют в своей собственной локальной среде.
R ищет переменные сначала в локальной среде, а затем в глобальной. Это похоже на то, как внутри функции переменная может иметь то же имя, что и переменная в глобальной среде, а R будет использовать локальное определение.
Благодаря тому, что определения аргументов функции формируют их собственную локальную среду, вы можете иметь значения аргументов по умолчанию на основе других значений аргументов, например
my.function <- function(x, two.x = 2 * x){}
Вот почему вы не можете ОПРЕДЕЛИТЬ функцию как,
my.function <- function(x = x){}
но вы можете ВЫЗЫВАТЬ функцию, используяmy.function(x = x)
. Когда вы определяете функцию, R сбивается с толку, потому что он находит аргументx =
как локальное значениеx
, но когда вы вызываете функцию, R находитx = 4
в локальной среде, из которой вы вызываете.Таким образом, помимо исправления ошибки путем изменения имени аргумента или явного указания среды, как указано в других ответах, вы также можете просто указать это
x=x
при вызове функции, а не при ее определении. Для меня указание этогоx=x
в вызове было лучшим решением, поскольку оно не требует дополнительного синтаксиса или накопления все большего количества имен переменных.источник
Мне нравится ответ Г. Гротендика , но мне было интересно, что в вашем случае проще не включать имена функций в параметры функций, например:
f <- function(x, T) { 10 * sin(0.3 * x) * sin(1.3 * x^2) + 0.001 * x^3 + 0.2 * x + 80 } g <- function(x, T) { exp(-f(x)/T) } test<- function(T = 1) { g(1,T) } test() ## [1] 8.560335e-37
источник