próbowałem realizuje funkcję let
z następujących semantyki:match.call zwany w niewłaściwym środowisku kiedy eval'ing
> let(x = 1, y = 2, x + y)
[1] 3
... co jest koncepcyjnie nieco podobny do substitute
ze składni with
.
Następujący kod prawie działa (powyższy wywołanie na przykład prace)
let <- function (...) {
args <- match.call(expand.dots = FALSE)$`...`
expr <- args[[length(args)]]
eval(expr,
list2env(lapply(args[-length(args)], eval), parent = parent.frame()))
}
Uwaga zagnieżdżony eval
zewnętrzna ocenić faktycznej ekspresji i wewnętrznego do oceny argumentów.
Niestety, ta ostatnia ocena dzieje się w niewłaściwym kontekście. Staje się to oczywiste, gdy próbuje zadzwonić let
z funkcją, która analizuje bieżącą klatkę, takich jak match.call
:
> (function() let(x = match.call(), x))()
Error in match.call() :
unable to find a closure from within which 'match.call' was called
myślałem o dostarczanie ramki nadrzędnej jako środowiska oceniającego dla eval
, ale to nie działa:
let <- function (...) {
args <- match.call(expand.dots = FALSE)$`...`
expr <- args[[length(args)]]
parent <- parent.frame()
eval(expr,
list2env(lapply(args[-length(args)], function(x) eval(x, parent)),
parent = parent)
}
Powoduje to ten sam błąd. Co prowadzi mnie do pytania: jak dokładnie oceniono match.call
? Dlaczego to nie działa? I, jak to zrobić?
Możliwe, że jest to istotne z '? Match.call':" Wywołanie "match.call" poza funkcją bez określenia "definicji" jest błędem. " A następnie spróbuj 'j <- function (x) x; j (match.call()) ', aby zobaczyć jedno miejsce, w którym wystąpił błąd. Nie rozgrywałam tego wszystkiego (i nie całkiem rozumiem, co naprawdę chcesz zrobić), ale może to być błąd, który jest specyficzny dla dziwnego sposobu używania 'match.call()' w to połączenie z anonimową funkcją. –
@Josh Nie sądzę, że jest to powiązane. Komunikat o błędzie jest inny, a kontekst, w którym nazywam 'match.call' jest * zdecydowanie * z wewnątrz funkcji, jeśli jest zły. –
Domyślam się, że sugerowałem, że 'match.call()' ma dość unikatowe reguły dotyczące zasięgu, które okazują się być specjalnie okablowane dla niego na poziomie C. (Kod definiujący 'do_matchcall', zawierający kilka interesujących komentarzy na temat tego, jak funkcja jest wywoływana, jest zapisany, jest w' $ R_SRC/src/main/unique.c'.) W przeciwieństwie do prawie każdej innej funkcji, nie jest dla mnie jasne, że to środowisko ewaluacyjne może być manipulowane/ustawiane przez wywołanie 'eval()'. Aby uprościć twój problem, może najpierw zorientuj się, dlaczego to nie działa (i jak można to zrobić): 'j <- function() eval (call (" match.call ")); j() '. –