3 Stimmen

Verwendung von Funktionen und Umgebungen

Im Anschluss an die jüngsten Diskussionen hier (z. B. 1 , 2 ) Ich verwende jetzt Umgebungen in einigen meiner Codes. Meine Frage ist, wie kann ich Funktionen erstellen, die Umgebungen entsprechend ihrer Argumente ändern? Zum Beispiel:

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    with(env, x+z)
}
f(y,z=1)

wirft

Error in eval(expr, envir, enclos) : object 'z' not found

Ich verwende Umgebungen, um zwei Simulationsgruppen gleichzeitig auseinander zu halten (ohne meinen Code zu überarbeiten, den ich für eine einzige Gruppe von Experimenten geschrieben habe).

8voto

Shane Punkte 95376

Die einfachste Lösung besteht darin, die Umgebung zu verwenden, wenn auf das Objekt verwiesen wird:

y <- new.env()
y$x <- 1
f <- function(env,z) {
    env$x+z
}
f(y,z=1)

Sie müssen Folgendes zuweisen z auch für Ihre Umgebung.

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    assign("z", z, envir=env)
    with(env, x+z)
}
f(y,z=1)

Eine andere Möglichkeit wäre, dass attach Ihre Umgebung, so dass die Variablen nun direkt verwendet werden können.

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    attach(env)
    y <- x + z
    detach(env)
    y
}
f(y,z=1)

Diese letztere Lösung ist sehr leistungsfähig, denn sie bedeutet, dass Sie jedes Objekt aus jeder angeschlossenen Umgebung in Ihrer neuen Umgebung verwenden können, aber sie bedeutet auch, dass Sie sehr vorsichtig sein müssen, was global zugewiesen wurde.

Editar :

Dies ist interessant, und ich verstehe das Verhalten nicht ganz (d. h. warum z fällt nicht in den Anwendungsbereich der with Anruf). Es hat etwas mit der ursprünglichen Erstellung der Umgebung zu tun, die dazu führt, dass sie außerhalb des Anwendungsbereichs der Funktion liegt, da diese Version funktioniert:

f <- function(z) {
    y <- new.env()
    with(y, x <- 1)
    with(y, x+z)
}
f(y,z=1)

3voto

hatmatrix Punkte 39643

Sie müssen nur eine Änderung vornehmen, damit Ihr Beispiel funktioniert - definieren Sie Ihre Funktion neu, damit sie substitute() um die gewünschten Werte im Rahmen von f() :

f <- function(env,z) {
    eval(substitute(x+z,list(z=z)), env)
}

Dies kann schnell unübersichtlich werden, zumal Sie sogar Zuweisungsanweisungen innerhalb von substitute() (zum Beispiel, ersetzen Sie x+z avec y <- x+z (nicht dass dies hier völlig relevant wäre), aber diese Entscheidung kann vom Entwickler getroffen werden...

Außerdem können Sie Folgendes ersetzen list(z=z) in dem obigen Substitutionsausdruck mit environment() (z.B., substitute(x+z,environment()) ), solange Sie keine widersprüchlichen Variablennamen zwischen denen haben, die an f() und denjenigen, die sich in Ihrer Umgebung aufhalten, aber vielleicht wollen Sie es nicht zu weit treiben.

Editar: Hier sind zwei weitere Möglichkeiten, von denen die erste nur dazu dient, die Flexibilität bei der Manipulation von Umgebungen zu zeigen, und die zweite sinnvoller ist, um sie tatsächlich zu nutzen.

1) Ändern Sie die umschließende Umgebung von 'env' (aber ändern Sie sie wieder auf den ursprünglichen Wert, bevor Sie die Funktion beenden):

f <- function(env,z) {
  e <- environment(env)
  environment(env) <- environment()
  output <- with(env,x+z)
  environment(env) <- e
  output
}

2) Erzwinge die Auswertung von 'z' in der aktuellen Umgebung der Funktion (mit environment() ), anstatt sie nach der Auswertung des Ausdrucks als freie Variable zu belassen, x+z , in 'env'.

f <- function(env,z) {
  with(environment(),with(env,x+z))
}

Je nach gewünschter Auflösungsreihenfolge können Sie im Falle widersprüchlicher Symbol-Wert-Zuordnungen - z. B. wenn Sie 'x' sowohl in Ihrer Funktionsumgebung als auch in der von Ihnen erstellten Umgebung 'y' definiert haben (welchen Wert von 'x' soll sie annehmen?) - den Funktionskörper stattdessen wie folgt definieren with(env,with(environment(),x+z)) .

1voto

Kenn Punkte 11
 y <- new.env()
 with(y, x <- 1)
 f <- function(env,z) {
    with(env, x+z)
 }
 f(y,z=1)

beachte die Klammern:) Das Folgende wird funktionieren:

with(env, x)+z

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X