2013-07-09 9 views
22

Dieser Beitrag (Lazy evaluation in R – is assign affected?) deckt einige Gemeinsamkeiten ab, aber ich bin mir nicht sicher, dass er meine Frage beantwortet.Warum wird die Verwendung schlecht zugewiesen?

Ich hörte assign mit, wenn ich die apply Familie eine ganze Weile zurück entdeckt, wenn auch rein aus Gründen der Eleganz in Situationen wie diese:

names.foo <- letters 
values.foo <- LETTERS 
for (i in 1:length(names.foo)) 
    assign(names.foo[i], paste("This is: ", values.foo[i])) 

, die ersetzt werden können:

foo <- lapply(X=values.foo, FUN=function (k) paste("This is :", k)) 
names(foo) <- names.foo 

Dies ist auch der Grund, warum dies (http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f) R-FAQ besagt, dass dies vermieden werden sollte.

Nun, ich weiß, dass assign allgemein verpönt. Aber gibt es andere Gründe, die ich nicht kenne? Ich vermute, dass es sich mit dem Scoping oder der faulen Bewertung herumschlagen könnte, aber ich bin mir nicht sicher? Beispielcode, der solche Probleme zeigt, wird groß sein.

Antwort

22

Eigentlich sind diese beiden Operationen sehr unterschiedlich. Der erste gibt Ihnen 26 verschiedene Objekte, während der zweite Ihnen nur einen gibt. Das zweite Objekt wird in Analysen viel einfacher zu verwenden sein. Ich schätze, ich würde sagen, Sie haben bereits den großen Nachteil von assign demonstriert, nämlich die Notwendigkeit, dann immer get zu verwenden, um alle ähnlich benannten Einzelobjekte zu korrellieren oder zu sammeln, die jetzt in der globalen Umgebung "lose" sind. Versuchen Sie sich vorzustellen, wie Sie mit diesen 26 separaten Objekten in der Regel etwas machen würden. Ein einfaches lapply(foo, func) wird für die zweite Strategie ausreichen.

Das FAQ-Zitat sagt eigentlich nur, dass die Verwendung von Zuweisung und die Zuweisung von Namen einfacher ist, aber nicht impliziert, dass es "schlecht" war. Ich lese es zufällig als "weniger funktional", da Sie tatsächlich keinen zugewiesenen Wert zurückgeben. Der Effekt scheint ein Nebeneffekt zu sein (und in diesem Fall führt die Strategie assign zu 26 separaten Nebenwirkungen). Die Verwendung von assign scheint von Leuten übernommen zu werden, die aus Sprachen kommen, die globale Variablen haben, um zu vermeiden, den "wahren Weg", d. H. Die funktionale Programmierung mit Datenobjekten, aufzunehmen. Sie sollten wirklich lernen, Listen zu verwenden, anstatt ihren Arbeitsbereich mit einzeln benannten Elementen zu beschmutzen.

Es gibt eine andere Zuordnung Paradigma, das verwendet werden kann:

foo <- setNames( paste0(letters,1:26), LETTERS) 

dass ein namens Atom-Vektor, anstatt eine benannte Liste erstellt, aber den Zugriff auf Werte in dem Vektor noch mit Namen gegeben [ erfolgt.

+0

In meinem Verständnis ist setNames nur ein versteckter 'Name <-'. Das ist ein anderes Haustier von mir! Gibt es einen besonderen Vorteil gegenüber "Namen"? – asb

+0

Warum sollte es ein "pet peeve" sein? Es ist leicht zu lesen und einige Leute bevorzugen den kompakteren Code. Mein Lieblingsärgernis benutzt Schleifen, wenn sie nicht gebraucht werden. –

+0

@asb wie wäre es 'sapply (X = values.foo, FUN = function (k) einfügen (" Das ist: ", k), vereinfachen = FALSE)' zu vermeiden, Ihre 'Namen <-' anrufen ... oder zu versteck es anders, schätze ich. – GSee

6

Ich möchte darauf hinweisen, dass assign mit environment s verwendet werden soll.

Von diesem Standpunkt aus betrachtet, wird mit dem „schlechte“, was in dem obigen Beispiel eine nicht ganz angemessene Datenstruktur (die Umwelt Basis anstelle einem list oder data.frame, vector, ...).

Randbemerkung: auch für environment s, die $ und $<- Operatoren arbeiten, so in vielen Fällen die expliziten assign und get ist es nicht notwendig, auch nicht.

+3

Und der übliche Grund, den sie auf 'assign' setzen, besteht darin, einen konstruierten Variablennamen zu erhalten, der nicht mit' $ <- 'funktioniert. Wir sollten also auch beachten, dass [[<-' "mit Umgebungen arbeitet, also könnte man folgendes tun:' myEnv [[paste0 ("mein", "Var", 1)]] <- Wert " –

9

Als Quelle von fortune(236) dachte ich, ich würde ein paar Beispiele hinzufügen (siehe auch fortune(174)).

Zuerst ein Quiz.Betrachten Sie den folgenden Code ein:

x <- 1 
y <- some.function.that.uses.assign(rnorm(100)) 

Nach den obigen 2 Zeilen Code ausgeführt wird, was ist der Wert von x?

Die Funktion assign wird verwendet, um "Aktion auf Distanz" zu bestätigen (siehe http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming) oder google dafür). Dies ist oft die Quelle von schwer zu findenden Fehlern.

Ich denke, das größte Problem mit assign ist, dass es Menschen dazu bringt, Denkwege zu verlassen, die sie von besseren Optionen wegführen. Ein einfaches Beispiel sind die 2 Code-Sätze in der Frage. Die lapply Lösung ist eleganter und sollte gefördert werden, aber die bloße Tatsache, dass Leute über die assign Funktion erfahren, führt Leute zur Schleifenoption. Dann entscheiden sie, dass sie die gleiche Operation für jedes in der Schleife erstellte Objekt ausführen müssen (was nur eine einfache lapply oder sapply wäre, wenn die elegante Lösung verwendet würde) und greifen auf eine noch kompliziertere Schleife mit get und apply zurück hässliche Anrufe zu paste. Dann werden die, verliebten mit assign versuchen so etwas wie zu tun:

curname <- paste('myvector[', i, ']') 
assign(curname, i) 

Und das ist nicht ganz, was sie erwartet, was dazu führt, entweder beschwerte sich über R (die als fair wie beschweren, dass mein Nachbar das Haus ist zu weit weg, weil ich entschied, den langen Weg um den Block zu gehen) oder noch schlimmer, vertiefen sich in Verwendung eval und parse, um ihre konstruierte Zeichenfolge zu "arbeiten" (was dann zu fortune(106) und führt).

Verwandte Themen