3 Stimmen

Veränderung der Elternumgebung des Closures in R (eine gute Idee)?

Ich habe nicht viel (beliebte) Literatur über die Manipulation von Funktionsumgebungen / die Verwendung von <<- in R gesehen (abgesehen von in adv-r). Insbesondere, was sind die Tabus von R in Bezug auf diese Dinge. Um diese Frage konkret zu machen, betrachten Sie die folgenden Funktionen:

appendOne <- function(env=parent.frame()) {
   tmp <- function(.x) {
     eval(substitute(.x <<- c(.x, "1")))
   }
   parent.env(environment(tmp)) <- env
   return(tmp)
}

g <- function() {
   .y <- 4
   appendOne()(.y)
   .y 
}

Der Zweck von appendOne ist ziemlich offensichtlich. Nun sind die Fragen (und ich verstehe, dass dies teilweise subjektiv ist):

  1. Was ist an dieser Strategie, Funktionen ausschließlich für ihre Seiteneffekte zu erstellen, in R gefährlich?
  2. Ist dieses Art von Programmiermuster "tabu" in R? Ich sehe nicht viel vom eval-substitute-Muster abgesehen von auf sehr hohen Ebenen. Liegt das daran, dass es schwer ist Anfängern zu erklären, oder weil es nicht ermutigt wird?

1voto

Die funktionale Programmierung fördert stark den Aufbau von Funktionen mit minimalen Seiteneffekten. Der Grund dafür ist, dass, wenn eine Funktion keine Seiteneffekte hat, es möglich ist, einen vollständigen Beweis für die Integrität ihres Verhaltens zu liefern -- sie wird nichts außerhalb ihrer eigenen lokalen Umgebung ändern.

Es kann jedoch gute Gründe geben, das eval(substitute(...))-Muster zu verwenden, um "in" die Aufrufumgebung einzudringen -- nämlich aus Gründen der Optimierung und der nicht standardmäßigen Auswertung, die die Benutzererfahrung deutlich verbessern.

Zum Beispiel führe ich in einem meiner Pakete eine sehr komplizierte Auswertung in der Aufrufumgebung durch, wobei ich sehr darauf achte, keine zufälligen lokalen Variablen zu definieren, da mir die Optimierung sehr wichtig war und ich nicht in C absteigen wollte.

Zum Beispiel, wenn Sie ein Dataframe in eine Funktion übergeben, eine Änderung in einer Spalte dieses Dataframes vornehmen und es dann zurückgeben, wird R das gesamte Dataframe kopieren. Sie können es in einer Umgebung einwickeln, die nur dieses Dataframe enthält, aber das macht es auch schwieriger zu verstehen. Die Verwendung von nicht standardmäßiger Auswertung kann die Leistung verbessern, wenn Sie wissen, dass der Benutzer sich der Seiteneffekte der zugrunde liegenden Funktion bewusst ist:

(function(df) eval.parent(substitute(df[[1]] <- 2 * df[[1]])))(iris)

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