Umfang und Bewertung von Funktionen in R.

8

Gegeben die folgende Funktion

f <- function(x) {
    g <- function(y) {
            y + z
    }
    z <- 4
    x + g(x)
 }

Wenn man den folgenden Code in R ausführt, warum ist die Antwort 10? Ich bin ein wenig verwirrt darüber, wie Sie in diese Frage hineinspielen.

z <- 10
f(3)
nzhanggh
quelle
2
Es bekommt das 'z' aus der Funktion env
akrun
5
Ist die Funktion nicht nur 4 + 2*xam Ende? Wobei 4 = z
Markus
1
@markus Ja, aber die Frage ist, warum ist z = 4? Es ist zu erwarten, dass die Funktionsdefinition z = 10 erfasst.
Robert Dodier
@RobertDodier Es sucht nach den Variablen in der ersten Umgebung, dh innerhalb der Funktion, findet sie und hört auf, nach anderen Stellen zu suchen, dh in der übergeordneten Umgebung. Sie können testen, indem Sie das 'z' innerhalb der Funktion z1 <- 4f(3)# [1] 16
umbenennen,
Oder geben Sie die Umgebung an, z <- 4; environment(g) <- .GlobalEnvund rufen z <- 10 > f(3) [1] 16
Sie

Antworten:

9

R verwendet lexikalisches Scoping. Wenn ein Objekt referenziert, aber nicht in einer Funktion definiert ist, wird es in der Umgebung gesucht, in der die Funktion definiert ist , und nicht in der Umgebung, aus der es aufgerufen wurde.

z wird in g referenziert, aber nicht in g definiert, so dass es sich um die Umgebung handelt, in der g definiert ist, und das ist die Umgebung innerhalb von f, also verwendet g z = 4.

Tatsächlich ist in diesem Fall die Umgebung, in der g definiert ist, dieselbe wie die Umgebung, aus der g aufgerufen wird. Daher muss jede Art, wie Sie es betrachten, z = 4 verwendet werden. Wenn Funktionen standardmäßig in der globalen Umgebung nach Objekten suchen, die nicht in der Funktion definiert sind, wird z = 10 verwendet, aber so funktioniert R nicht.

Damit es anders funktioniert

Wenn Sie aus irgendeinem Grund g zwingen möchten, in der Umgebung, in der f aufgerufen wird, nach z zu suchen, können Sie dies tun (wobei parent.frame()sich auf die Umgebung bezieht, aus der f aufgerufen wird).

f2 <- function(x, envir = parent.frame()) {
    g <- function(y) {
            y + with(envir, z)
    }
    z <- 4
    x + g(x)
 }
 z <- 10
 f2(3)
 ## [1] 16

oder wir könnten verwenden, y + envir$zaußer dass dies nur im übergeordneten Frame und nicht in seinen Vorfahren angezeigt withwird, wohingegen Vorfahren des übergeordneten Frames angezeigt werden, wenn sie nicht im übergeordneten Frame gefunden werden.

Eine Alternative besteht darin, die Umgebung von g so zu ändern, dass envirnach Objekten gesucht wird, die nicht in g gefunden wurden:

f3 <- function(x, envir = parent.frame()) {
    g <- function(y) {
            y + z
    }
    environment(g) <- envir
    z <- 4
    x + g(x)
 }
 z <- 10
 f3(3)
 ## [1] 16
G. Grothendieck
quelle