From p.dalgaard at biostat.ku.dk  Sat Oct 28 00:08:24 2006
From: p.dalgaard at biostat.ku.dk (Peter Dalgaard)
Date: 28 Oct 2006 00:08:24 +0200
Subject: [Rd] as.missing
In-Reply-To: <Pine.LNX.4.64.0610271126070.7708@nokomis.stat.uiowa.edu>
References: <453E462C.6050103@bank-banque-canada.ca>
	<971536df0610250928q615c2e4dl950e8f576c492789@mail.gmail.com>
	<4540CC71.1010108@bank-banque-canada.ca>
	<971536df0610261830o4d36376bk4b90d42e218eb2d0@mail.gmail.com>
	<m0hcxq3z2a.fsf@bar.nemo-project.org>
	<45420FE2.5090000@bank-banque-canada.ca>
	<x2pscdltv9.fsf@turmalin.kubism.ku.dk>
	<4542260D.2000606@bank-banque-canada.ca>
	<x2mz7hzs0a.fsf@turmalin.kubism.ku.dk>
	<45422B7D.204@bank-banque-canada.ca>
	<Pine.LNX.4.64.0610271126070.7708@nokomis.stat.uiowa.edu>
Message-ID: <x21wot9ztz.fsf@turmalin.kubism.ku.dk>

Luke Tierney <luke at stat.uiowa.edu> writes:

> There are lot of subtle issues involved here. We should think through
> carefuly exactly what semantics we want for missing value propagation
> before making any changes.  Making usage easy at top level is
> genearlly a good thing, but for usage within functions eliminating
> error messages by making more automated choices may not be a good
> thing--it may mask real mistakes.
> 
> There are also issues with the internal implementation if missing
> arguments we ned to think carefuly about before exposing them at teh R
> level.  The fact that internally there is a missing argument token
> does not mean it is a good thing to expose that detail at the R level
> (and it already is in call objects and creates some issues with
> computing on the language.
> 
> Like I said, it's complicated, so let's not leap before we look
> carefully.

I think I'm beginning to realize what the problem really is: 

It would (conceptually, at least) be fairly simple to change the
current semantics of evaluating an argument to be like

   if (x is a promise)
     evaluate its expression part
   if (value is missing)
     if (there's a default)
         x <- evaluate default
     else
         x <- .Missing # missing value marker 

Then, if you have a chain where f1(x) calls f2(x) calls .... fn(x),  
and x is missing in the first call, fn() will see the first default
for x among f1, f2, ...., f(n-1) if any exists. 

One problem with this is when to declare an Error. It may or may not
be an error to have something evaluating to .Missing, depending on the
context in which the evaluation occurs. I'm pretty sure that is a Bad
Thing design-wise.

Another problem is that, currently, argument passing works by
assigning a promise to the name, which is either a promise to evaluate
the default expression or to evaluat the one in the actual argument.
With the change, you'd need to be able to evaluate defaults, even when
an expression has been passed as an argument, which probably means
that promises need to be three-pronged structures (value, expression,
default expression), or that you have to keep the formal argument list
around in the evaluation frame.


> Best,
> 
> luke
> 
> On Fri, 27 Oct 2006, Paul Gilbert wrote:
> 
> >
> 
> Peter Dalgaard wrote:
> 
> >Paul Gilbert <pgilbert at bank-banque-canada.ca> writes:
> >
> >
> >>Peter Dalgaard wrote:
> >>
> >>
> >>>Paul Gilbert <pgilbert at bank-banque-canada.ca> writes:
> >>>
> >>>
> >>>
> >>>>>I.e., when x is missing in g, and g calls f(3,x), f will use its
> >>>>>default value for x.
> >>>>>
> >>>>>
> >>>>Yes, that is the behaviour I am looking for. That is, f  should do
> >>>>what it normal would do if it were called with x missing.
> >>>>
> >>>>
> >>>But if x has a default in g then that default should presumably be
> >>>used?
> >>>
> >>Yes.  The value of x in g would get passed to f, default or otherwise.
> >>If that value is something that indicates x is missing, then it should
> >>be treated as if it is missing in f. This means f should use its
> >>default value, rather than throw an error saying x is missing.
> >>
> >>
> >>>And what if x is given a value in the evaluation frame of g
> >>>before it is used by f (which can happen, you know, even after the
> >>>evaluation of f has begun)? Now imagine a longer chain of calls.
> >>>
> >>>I think what you're asking for is essentially dynamic scoping for
> >>>missing arguments: you'd have to backtrack along the call chain to
> >>>find the first instance where x is either given a value or has a
> >>>default. This sounds messy.
> >>>
> >>>
> >>You understand this better than I do, but I don't think I am asking to
> >>do this. Currently I think f  looks back too far and finds x is
> >>missing and g does not have a default value for x, so it throws an
> >>error.  Why can't f find its own default value for x?
> >>
> >
> >Because it's being told to use the value of the argument instead. I
> > think. This stuff is treacherous. E.g. what would you expect from
> > this?
> >
> >g <- function(x) {f <- function(y) {x <<- 1; y} ; f(x)}
> >g()
> >
> >
> I'm confused.  Neither f nor g have a default here, so I don't think
> this is related to what I'm talking about. Currently, in your example,
> f find x with a value of 1, and I am not suggesting changing that. I'm
> only suggesting that if f finds x is missing, it should look at it's
> own default argument.

You can add defaults if you want. The thing I was illustrating is that
even though a missing x is passed for y, this is not checked until y
is needed, by which time x might have become non-missing. The point is
that even if you had 

g <- function(x) {f <- function(y=2) {x <<- 1; y} ; f(x)}

then once the f is called, y is a promise to evaluate x in g's frame
and the default expression is lost.

-- 
   O__  ---- Peter Dalgaard             ?ster Farimagsgade 5, Entr.B
  c/ /'_ --- Dept. of Biostatistics     PO Box 2099, 1014 Cph. K
 (*) \(*) -- University of Copenhagen   Denmark          Ph:  (+45) 35327918
~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk)                  FAX: (+45) 35327907




[Rd] as.missing
Peter Dalgaard