2013-07-09 16 views
22

Ten wpis (Lazy evaluation in R – is assign affected?) obejmuje kilka wspólnych spraw, ale nie jestem pewien, czy odpowiada na moje pytanie.Dlaczego przypisywanie jest złe?

ja przestałem używać assign kiedy odkryłem rodzinę apply dość jakiś czas temu, aczkolwiek czysto ze względu na elegancję w sytuacjach takich jak ta:

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

który może być zastąpiony przez:

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

Jest to również powód tego (http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f) R-faq mówi, że należy tego unikać.

Teraz wiem, że assign jest ogólnie mile zaskoczony. Ale czy są inne powody, których nie znam? Podejrzewam, że może zepsuć ocenę lub leniwe oceny, ale nie jestem pewien? Przykładowy kod demonstrujący takie problemy będzie świetny.

Odpowiedz

22

W rzeczywistości te dwie operacje są zupełnie inne. Pierwszy daje 26 różnych obiektów, podczas gdy drugi daje tylko jeden. Drugi obiekt będzie o wiele łatwiejszy w użyciu w analizach. Sądzę, że powiedziałbym, że już zademonstrowałeś poważny minus assign, a mianowicie konieczność, aby zawsze używać get do corrallingu lub zbierania wszystkich podobnie nazwanych pojedynczych obiektów, które są teraz "luźne" w środowisku globalnym. Spróbuj wyobrazić sobie, jak serialnie zrobiłbyś coś z tymi 26 oddzielnymi obiektami. Wystarczy prosta lapply(foo, func) dla drugiej strategii.

Ten cytat z listy najczęściej mówi tylko, że używanie przypisania i przypisywanie nazw jest łatwiejsze, ale nie oznacza, że ​​było "złe". Zdaję sobie sprawę, że jest to "mniej funkcjonalny", ponieważ nie zwracasz wartości, która zostanie przypisana. Efekt wygląda na efekt uboczny (w tym przypadku strategia assign daje 26 oddzielnych efektów ubocznych). Wydaje się, że użycie assign jest przyjmowane przez ludzi, którzy pochodzą z języków, które mają zmienne globalne, jako sposób uniknięcia podnoszenia "True R Way", tj. Programowania funkcjonalnego z obiektami danych. Naprawdę powinni nauczyć się korzystać z list, a nie zaśmiecać swojego miejsca pracy z indywidualnie nazwanymi przedmiotami.

Jest inny paradygmat zadanie, które można stosować:

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

To tworzy nazwie wektor atomową zamiast nazwanego liście, ale dostęp do wartości w wektorze jest jeszcze zrobione z nazw podanych do [.

+0

W moim rozumieniu setNames jest po prostu ukrytym 'imionami <-'. który jest moim kolejnym zwierzakiem! Czy istnieje szczególna przewaga nad "nazwami"? – asb

+0

Dlaczego powinien to być "zirytowany zwierzak"? Jest łatwy do odczytania, a niektórzy wolą bardziej zwarty kod. Mój zwierzak korzysta z pętli, gdy nie są potrzebne. –

+0

@asb jak o 'sapply (X = values.foo, FUN = funkcja (k) wklej (" To jest: ", k), upraszczaj = FALSE)', aby ominąć twoje 'name <-' call ... lub ukryj to inaczej, jak sądzę. – GSee

6

Chciałbym podkreślić, że assign ma być używany z environment s.

Z tego punktu widzenia "zła" rzecz w powyższym przykładzie wykorzystuje niezbyt odpowiednią strukturę danych (środowisko bazowe zamiast list lub data.frame, vector, ...).

Side uwaga: również na environment s, praca $$<- i operatorów, więc w wielu przypadkach wyraźny assign i get nie jest konieczne tam, ani.

+3

I zwykłym powodem, dla którego odwołują się do 'assign', jest uzyskanie konstruowanej nazwy zmiennej, która nie działa z' $ <- '. Powinniśmy również zauważyć, że '[[<-'" działa "w środowiskach, więc można zrobić:' myEnv [[paste0 ("my", "Var", 1)]] <- wartość' –

9

Jako źródło fortune(236) pomyślałem, że dodaję kilka przykładów (zobacz także fortune(174)).

Najpierw quiz.Rozważmy następujący kod:

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

Po uruchomieniu powyżej 2 linie kodu, co jest wartością x?

Funkcja assign służy do zatwierdzania "Działania na odległość" (patrz http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming) lub google). Często jest to źródłem trudnych do znalezienia błędów.

Myślę, że największym problemem z assign jest to, że prowadzi ludzi do myślenia, które odciągają ich od lepszych opcji. Prostym przykładem są 2 zestawy kodu w pytaniu. Rozwiązanie lapply jest bardziej eleganckie i powinno być promowane, ale sam fakt, że ludzie dowiadują się o funkcji assign prowadzi ludzi do opcji pętli. Następnie decydują, że muszą wykonać tę samą operację na każdym obiekcie utworzonym w pętli (co byłoby kolejnym prostym rozwiązaniem, gdyby zastosowano elegancki roztwór) i zastosować jeszcze bardziej skomplikowaną pętlę obejmującą zarówno get, jak i apply brzydkie połączenia z numerem paste. Wtedy ci zachwycona assign spróbować zrobić coś takiego:

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

I że nie robi zupełnie co oni oczekiwać co prowadzi albo narzekają R (która jest tak piękna jak narzekają, że dom mój sąsiad jest zbyt daleko z dala, ponieważ zdecydowałem się przejść długą drogę dookoła bloku) lub, co gorsza, zagłębić się w używanie eval i parse, aby skonstruować ich ciąg do "pracy" (która następnie prowadzi do fortune(106) i fortune(181)).

Powiązane problemy