belofte al onder evaluatie: recursieve standaardargumentreferentie of eerdere problemen?

Hier is mijn R-code. De functies zijn gedefinieerd als:

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)
}

De lopende fout is:

> test()
Fout in test() :
belofte die al wordt geëvalueerd: recursieve verwijzing naar standaardargumenten of eerdere problemen?

Als ik de definitie van fvervang door die van g, dan verdwijnt de fout.

Ik vroeg me af wat de fout was? Hoe dit te corrigeren als de definitie van fniet wordt vervangen door die van g? Bedankt!


Bijwerken:

Bedankt! Twee vragen:

(1) als de functie testverder een argument voor fneemt, voeg je dan iets toe als test <- function(g.=g, T=1, f..=f){ g.(1,T, f.=f..) }? Is het in gevallen met meer recursie een goede en veilige gewoonte om meer .toe te voegen?

(2) als feen niet-functioneel argument is, bijvoorbeeld g <- function(x, T, f=f){ exp(-f*x/T) }en test <- function(g.=g, T=1, f=f){ g.(1,T, f=f.) }, zullen dezelfde naam voor zowel formele als feitelijke niet-functionele argumenten een goede en veilige praktijk of kan het mogelijke problemen veroorzaken?


Antwoord 1, autoriteit 100%

Formele argumenten van de vorm x=xveroorzaken dit. Als we de twee gevallen waarin ze voorkomen, elimineren, krijgen we:

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) {  ## 1. note f.
   exp(-f.(x)/T) 
}
test<- function(g. = g, T = 1) {  ## 2. note g.
   g.(1,T) 
}
test()
## [1] 8.560335e-37

Antwoord 2, Autoriteit 12%

Als u de evaluatiecontext van het argument beïnvloedt, vermijdt u het probleem van dezelfde naam:

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

Antwoord 3, Autoriteit 6%

Zoals reeds vermeld, komt het probleem van het hebben van een functie-argument gedefinieerd als zichzelf. Ik wil echter een uitleg toevoegen van WAAROM Dit is een probleem, omdat het begrip dat me heeft geleid tot een eenvoudige (voor mij) manier om het probleem te voorkomen: geef gewoon het argument in de oproep in plaats van de definitie .

Dit werkt niet:

x = 4
my.function <- function(x = x){} 
my.function() # recursive error!

Maar dit werkt:

x = 4
my.function <- function(x){} 
my.function(x = x) # works fine!

Functie-argumenten bestaan ​​in hun eigen lokale omgeving.

R Zoekt eerst naar variabelen in de lokale omgeving, dan in de wereldwijde omgeving. Dit is net als hoe in een functie een variabele kan dezelfde naam hebben als een variabele in de wereldwijde omgeving, en r zal de lokale definitie gebruiken.

Het hebben van functie-argument Definities vormen hun eigen lokale omgeving is waarom u standaard argumentwaarden kunt hebben op basis van andere argumentwaarden, zoals

my.function <- function(x, two.x = 2 * x){}

Dus dit is waarom u geen functie kunt definiëren als my.function <- function(x = x){}maar u kunt de functie bellen met my.function(x = x). Wanneer u de functie definieert, wordt r verward, want het vindt het argument x =als de lokale waarde van x, maar wanneer u de functie r zoekt vindt x = 4In de lokale omgeving waarin u belt.

Dus naast het vaststellen van de fout door de naam van de argument te wijzigen of expliciet de omgeving op te geven zoals vermeld in andere antwoorden, kunt u ook gewoon aangeven dat x=xwanneer u de functie belt in plaats van wanneer Je definieert het. Voor mij was het opgeven van dat x=xin de oproep de beste oplossing was, omdat het geen extra syntaxis inhoudt of meer en meer variabele namen verzamelt.


Antwoord 4

Ik hou van de G. Grothendieck Antwoord, maar ik vroeg me af of dat eenvoudiger is in je geval om geen functienamen in de parameters van functies te bevatten, zoals deze:

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

Other episodes