From ggrothendieck at gmail.com  Fri Oct 27 18:24:12 2006
From: ggrothendieck at gmail.com (Gabor Grothendieck)
Date: Fri, 27 Oct 2006 12:24:12 -0400
Subject: [Rd] as.missing
In-Reply-To: <971536df0610261830o4d36376bk4b90d42e218eb2d0@mail.gmail.com>
References: <453E462C.6050103@bank-banque-canada.ca>
	<971536df0610250928q615c2e4dl950e8f576c492789@mail.gmail.com>
	<4540CC71.1010108@bank-banque-canada.ca>
	<971536df0610261830o4d36376bk4b90d42e218eb2d0@mail.gmail.com>
Message-ID: <971536df0610270924i284467c1q226404f8060f8628@mail.gmail.com>

On 10/26/06, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
> This is what I get:
>
> > as.missing <- force
> > f <- function(y, x=1) {cat(missing(x)) ; x}
> > g <- function(x=as.missing()) f(3,x)
> > g()
> FALSEError in as.missing() : argument "x" is missing, with no default
> > traceback()
> 3: as.missing()
> 2: f(3, x)
> 1: g()
> > traceback()
> 3: as.missing()
> 2: f(3, x)
> 1: g()
>
> so g did in fact pass the missing to f and it was only f that blew up,
> not g.  If that's not what you want please explain.
>
>
> On 10/26/06, Paul Gilbert <pgilbert at bank-banque-canada.ca> wrote:
> > I don't see how this solves the problem.
> >
> >  > as.missing <- force
> >  >  f <- function(y, x=1) {cat(missing(x)) ; x}
> >  > g <- function(x) f(3,x)
> >  > g(1)
> > FALSE[1] 1
> >  > g()
> > TRUEError in f(3, x) : argument "x" is missing, with no default
> >
> > I think I still have to put all the logic in g() to figure out if the
> > argument is missing, rather than the nice clean solution of just passing
> > the argument along to the function it calls. How does this differ from
> > the problem I already have when I  specifying the argument as NULL and
> > do all the checking in  g?
> >
> > Paul
> >
> > Gabor Grothendieck wrote:
> >
> > > You can do it like this:
> > >
> > >> as.missing <- force
> > >> g <- function(x = as.missing()) missing(x)
> > >> g(3)
> > >
> > > [1] FALSE
> > >
> > >> g()
> > >
> > > [1] TRUE
> > >
> > > On 10/24/06, Paul Gilbert <pgilbert at bank-banque-canada.ca> wrote:
> > >
> > >> (I'm not sure if this is a request for a feature, or another instance
> > >> where a feature has eluded me for many years.)
> > >>
> > >> Often I have a function which calls other functions, and may often use
> > >> the default arguments to those functions, but needs the capability to
> > >> pass along non-default choices. I usually do this with some variation on
> > >>
> > >> foo <- function(x, foo2Args=NULL or a list(foo2defaults),
> > >>                    foo3Args=NULL or a list(foo3defaults))
> > >>
> > >> and then have logic to check for NULL, or use the list in combination
> > >> with do.call.  It is also possible to do this with ..., but it always
> > >> seems a bit dangerous passing all the unnamed arguments along to all the
> > >> functions being called, especially when I always seem to be calling
> > >> functions that have similar arguments (maxit, eps, start, frequency,
> > >> etc).
> > >>
> > >> It is a situation I have learned to live with, but one of my
> > >> co-maintainers just pointed out to me that there should be a good way to
> > >> do this in R.  Perhaps there is something else I have missed all these
> > >> years?  Is there a way to do this cleanly? It would be nice to have
> > >> something like
> > >>
> > >> foo <- function(x, foo2Args=as.missing(),  foo3Args=as.missing())
> > >>
> > >> then the call to foo2 and foo3 could specify  foo2Args and foo3Args, but
> > >> these would get treated as if they were missing, unless they are given
> > >> other values.
> > >>
> > >> Paul Gilbert
> > >
> > ====================================================================================
> >
> > La version fran?aise suit le texte anglais.
> >
> > ------------------------------------------------------------------------------------
> >
> > This email may contain privileged and/or confidential information, and the Bank of
> > Canada does not waive any related rights. Any distribution, use, or copying of this
> > email or the information it contains by other than the intended recipient is
> > unauthorized. If you received this email in error please delete it immediately from
> > your system and notify the sender promptly by email that you have done so.
> >
> > ------------------------------------------------------------------------------------
> >
> > Le pr?sent courriel peut contenir de l'information privil?gi?e ou confidentielle.
> > La Banque du Canada ne renonce pas aux droits qui s'y rapportent. Toute diffusion,
> > utilisation ou copie de ce courriel ou des renseignements qu'il contient par une
> > personne autre que le ou les destinataires d?sign?s est interdite. Si vous recevez
> > ce courriel par erreur, veuillez le supprimer imm?diatement et envoyer sans d?lai ?
> > l'exp?diteur un message ?lectronique pour l'aviser que vous avez ?limin? de votre
> > ordinateur toute copie du courriel re?u.
> >
>

How about using this is.missing() instead of missing():


> is.missing <- function(x) {
+
+ mc <- match.call()
+ mc[[1]] <- as.name("missing")
+ missing <- eval.parent(mc)
+
+ xc <- deparse(substitute(x))
+ fo <- formals(sys.function(-1))
+ has.default <- !identical(fo[[xc]], alist(dummy=)[[1]])
+
+ if (has.default) {
+    mc <- match.call(sys.function(-1), call = sys.call(-1))
+    miss <- !(xc %in% names(mc))
+    miss <- miss || missing
+    if (missing)
+       eval.parent(substitute(x <- default, list(default = fo[[xc]])))
+    p <- parent.frame()
+    miss
+ } else missing
+ }
>
> g1 <- function(x = 3, y = 5, z) {
+ im <- is.missing(x)
+ print(im)
+ print(x)
+ }
> g1()
[1] TRUE
[1] 3
> f1 <- function(x) g1(x)
> f1()
[1] TRUE
[1] 3
> f1(10)
[1] FALSE
[1] 10
>
> g2 <- function(x = 3, y = 5, z) {
+ im <- if (is.missing(x)) TRUE else FALSE
+ print(im)
+ print(x)
+ }
> g2()
[1] TRUE
[1] 3
> f2 <- function(x) g2(x)
> f2()
[1] TRUE
[1] 3
> f2(20)
[1] FALSE
[1] 20
>
> ### this one does not seem to work -- is.missing can't be passed as arg
> g3 <- function(x = 3, y = 5, z) {
+ cat(is.missing(x), x, "\n")
+ }
>
> g3()
TRUE
> g3(30)
TRUE 30
>
> f3 <- function(x) g1(x)
> f3()
[1] TRUE
[1] 3
>
> gz <- function(x = 3, y = 5, z) {
+ im <- is.missing(z)
+ print(im)
+ try(print(z))
+ }
> gz()
[1] TRUE
Error in print(z) : argument "z" is missing, with no default
>




[Rd] as.missing
Gabor Grothendieck