Warum "fehlt" und default-Argumente werden in der Funktion `lapply`?
Ich bin erstaunt, dass missing
scheint nicht zu arbeiten, in einer Funktion, die aufgerufen wird, indem lapply
. Angenommen ich haben die folgenden Funktionen:
.add <- function(x, arg, ...) {
if (missing(arg)) {
arg <- 1
}
print(match.call())
return(x + arg)
}
wrapper <- function(l, arg, ...) {
return(lapply(l, .add, arg=arg, ...))
}
Einstellung arg
explizite arbeiten wie vorbehalten:
wrapper(list(x=1:10, y=1:10), arg=1)
#FUN(x = X[[1L]], arg = ..1)
#FUN(x = X[[2L]], arg = ..1)
#$x
# [1] 2 3 4 5 6 7 8 9 10 11
#
#$y
# [1] 2 3 4 5 6 7 8 9 10 11
Ohne arg
ich würde erwarten, dass die gleiche Ausgabe, aber es funktioniert nicht:
wrapper(list(x=1:10, y=1:10))
#FUN(x = X[[1L]], arg = ..1)
# Error in FUN(X[[1L]], ...) : argument "arg" is missing, with no default
missing
arbeitet in geschachtelte wrapper-Funktionen, bei denen keine lapply
verwendet wird.
Warum es scheint, haben keine Wirkung in der Funktion von lapply
?
BEARBEITEN: Default-Argumente auch nicht arbeiten:
.add <- function(x, arg=5, ...) {
if (missing(arg)) {
arg <- 1
}
print(match.call())
return(x + arg)
}
wrapper(list(x=1:10, y=1:10))
#FUN(x = X[[1L]], arg = ..1)
# Error in FUN(X[[1L]], ...) : argument "arg" is missing, with no default
Scheint es, dass arg
ist weder fehlt noch zugänglich. Was ist hier passiert?
(Ich weiß, dass ich könnte dies umgehen, indem Sie die Einstellung arg=NULL
im wrapper
und if (is.null(arg))
im .add
oder etwas anderes. .add
ist eine interne Funktion, die bestimmt arg
durch seine eigene, basierend auf der Eingabe (z.B. arg=mean(x)
), und ich will arg
im wrapper
zu dokumentieren, das argument arg
für den Benutzer und ermöglichen dem Benutzer das überschreiben der default-Verhalten. Und am wichtigsten: ich will verstehen warum das wird nicht funktionieren!)
EDIT2: Endlich ist dieses Verhalten behoben. Es war ein bug in R < 3.2.0 finden Sie PR#15707.
- Ich denke, das problem ist in
wrapper
nichtlapply
. Entfernen Sie das formale argumentarg
auswrapper
ganz (oder gibt es ein Standard) und es funktioniert für mich. - Aus der Dokumentation
?missing
: Derzeitmissing
kann nur verwendet werden, in der unmittelbaren Körper-von der Funktion, die definiert, das argument, nicht in den Körper einer verschachtelten Funktion oder ein lokaler Aufruf. Dies kann sich in Zukunft ändern. Funktioniert diese Hilfe? - Das ist richtig, aber
.add
ist eine interne Funktion und die Funktion dokumentiert istwrapper
(und die möglichen Standard-argument vonarg
würde davon abhängen, die Teilmenge, die.add
). - Du hast Recht, aber so funktioniert es:
wrapper2 <- function(x, arg) { return(.add(x, arg=arg)) }
- Ich bin sehr neugierig zu wissen, warum das passiert... ich habe versucht, für eine ganze Weile zu verstehen, aber noch nicht da. Ich werde zurück schreiben, wenn ich etwas finden. Oder vielleicht ist es Zeit, meine erste bounty! 🙂
- Siehe meine Antwort für das, was ich herausgefunden habe.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Werde ich zunächst erwähnen, dass ich glaube, dass die idiomatischen Weg dies zu tun ist, indem er einen Anruf und dann zu bewerten. Sehen
write.csv
für ein Beispiel. Ich glaube, dieser code tut, was Sie möchten, mit dieser Methode.Ok, hier ist nun ein Versuch, zu erklären, die Probleme, die Sie entdeckt. Ich stehe bereit, korrigiert zu werden, als gut, aber hoffentlich wird dies wenigstens helfen, klären die Fragen, wie @idfah Antwort haben.
Zunächst werde ich die Bewältigung der "defaults" - Problem, wie ich denke, es ist mehr einfach. Dieses ich denken kann gemacht werden einfacher, da in den beiden folgenden Funktionen, wobei die zweite (
f2
) ruft einfach die erste (f1
). Was wir sehen, ist, dass das Standard-argument inf1
wird überschrieben durch das Versprechenx
imf2
, und wenn das Versprechen ausgewertet wird, vorhanden ist. Moral von dieser Geschichte (finde ich); Standard: muss festgelegt werden, wieder in das aufrufende Funktion, wenn die variable enthalten ist, in den Aufruf.Nun zu den fehlenden in
lapply
Problem. Hier bin ich im Grunde genommen haben sgibb code, aber haben Hinzugefügt, eine Nachricht darüber, ob es nicht arg ist, als vermisst. Haben wir, was scheint zu sein eine merkwürdige Widerspruch; die Nachricht sagt uns, dassarg
fehlt NICHT, aber wenn die Funktion versucht, darauf zuzugreifen, bekommen wir eine Fehlermeldung, die uns sagt, dassarg
fehlt.Was ich denke, passiert ist, das
lapply
ist, dass wir die Versprechenarg
im..1
, also es sieht nicht so fehlen, aber wenn er versucht, es zu bewerten, es findet, dass es fehlt. Moral von dieser Geschichte (finde ich); Versuch nicht, Sie zu propagieren missings durchlapply
.UPDATE: genauer gesagt, es etwas wie ein dot expansion arbeitet. Betrachten Sie diese version von
lapply
(die ja eigentlich nicht arbeiten, auf einer Liste, aber ansonsten hat die gleiche code-Stil); dies zeigt, bekommen wir das gleiche Verhalten.Aber wenn wir ersetzen die Punkte durch eine variable Namen, funktioniert es wie erwartet.
Und noch ein Beispiel; wenn ich mit dots, aber die expansion selbst, durch die Berufung
..1
direkt, es funktioniert auch! Dies ist neugierig, wie die aufeinander abgestimmten call ist die gleiche wie die version, die nicht funktioniert...1
) arbeitet und die automatische fehlschlägt?missing
(ist nur aufgefallen, das beim Debuggen einer Funktion und stolperte über dieses Q&A). z.B.f1 <- function(x=1) missing(x); f1()
match.call
in Ihre Funktion und Ihre Entdeckung macht ein wenig mehr Sinn.f1 <- function(x=1) {match.call(x); x}; f1()
Gibt es keine
missing
in Ihre wrapper, so dass es Bomben gibt. In diesem Fall, Sie brauchen es nicht, da Sie mithilfe von variadic Argumente sowieso. Versuchen Sie dies:Wenn der wrapper muss wissen
arg
, dann müssen Sie einemissing
es:Ich stehe korrigiert
Das folgende Beispiel erlaubt die
missing
werden am unteren Rand des call-stack, vermutlich wegen der lazy evaluation. Ich bin nicht sicher, warum dein Beispiel nicht funktioniert... neugierig.arg
hängt von der Teilmenge, die in.add
(z.B. so etwas wiemean(x)
).arg
als parameterwrapper
aber keinemissing
im wrapper, dann ist dein Programm Bomben, bevor es überhaupt Anrufe.add
Scheint logisch für mich. Wenn Sie Ihre Argumente an-wrapper sind alle Variable, dann loszuwerden, die arg inwrapper
.add
sonst werden Sie nicht sehen, die Ausgabe vonprint(match.call())
. IMHOarg
wird zuerst ausgewertet, wenn inreturn(x + arg)
(lazy evaluation).