On Wed, Jul 17, 2013 at 10:20 AM, Ben Bolker <bbolker@gmail.com> wrote:

> Brian Rowe <rowe <at> muxspace.com> writes:
>
> >
> > Thanks for the lead. Given the example in ?missing though,
> >  wouldn't it be safer to explicitly define a
> > default value of NULL:
> >
> > myplot <- function(x, y=NULL) {
> >   if(is.null(y)) {
> >     y <- x
> >     x <- 1:length(y)
> >   }
> >   plot(x, y)
> > }
> >
>
>  [snip]
>
>  In my opinion the missing() functionality can indeed be
> fragile (for example, I don't know how I can manipulate an
> existing call to make an argument be 'missing' when it was
> previously 'non-empty')


Like so:

> thecall <- quote(x[i,j])
> thecall[[3]] <- quote(expr=)
> thecall
x[, j]


> and using an explicit NULL is often
> a good idea.  This makes the documentation a tiny bit less
> wieldy if you have lots of parameters ...


I could certainly imagine a variant of R in which missing and NULL are
unified, and NULL is the default for any binding that exists but was not
given a value. I would probably prefer it on the grounds of being smaller
and more consistent.  (At the C implementation level, R_MissingArg and
R_NilValue are just two parallel uses of the null object pattern with
different behavior, which is a bit silly)

But one advantage the missing value behavior can have is that it "fails
early", i.e. it generates an error closer to where a function wants to use
a value it was not provided, rather than "failing late," where a NULL
propagates though your data and you have to do more debugging work to find
out where it came from. This kind of fragility can be a good thing as it's
easier to debug problems that happen closer to the point of failure.

For instance,

> myplot <- function(y, x=1:length(y)) plot(x,y)
> myplot()
Error in plot(x, y) (from #1) :
  error in evaluating the argument 'x' in selecting a method for function
'plot': Error in length(y) (from #1) : 'y' is missing

I didn't think about what myplot should do with no arguments. As it turns
out it is an error, as R refuses to pass a missing value along to length()
or plot(), which is reasonable.

Compare with a default-NULL version.
> myplot <- function(y=NULL, x=1:length(y)) plot(x,y)
> myplot()

Instead of failing early and generating a stack trace pointing you at the
problem, myplot() now generates a graph with points at (0,0) and (1,1) --
most surprising! This is because R happily forwards NULL to length() and
plot() where it refused to earlier. In more complicated code nulls can pass
along several layers before causing problems, making those problems more of
a headache to debug.

Peter

	[[alternative HTML version deleted]]

