Is missingness always passed on?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Is missingness always passed on?

Duncan Murdoch-2

There's a StackOverflow question
https://stackoverflow.com/q/22024082/2554330 that references this text
from ?missing:

"Currently missing can only be used in the immediate body of the
function that defines the argument, not in the body of a nested function
or a local call. This may change in the future."

Someone pointed out (in https://stackoverflow.com/a/58169498/2554330)
that this isn't true in the examples they've tried:  missingness does
get passed along.  This example shows it (this is slightly different
than the SO example):

f1 <- function(x, y, z){
   if(missing(x))
     cat("f1: x is missing\n")
   if(missing(y))
     cat("f1: y is missing\n")
}

f2 <- function(x, y, z){
   if(missing(z))
     cat("f2: z is missing\n")
   f1(x, y)
}

f2()

which produces

f2: z is missing
f1: x is missing
f1: y is missing

Is the documentation out of date?  That quote appears to have been
written in 2002.

Duncan Murdoch

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Is missingness always passed on?

R devel mailing list
There is "missing with default" and "missing without default".

If an argument x is missing without a default, then missing(x) is true, if
you pass x to another function, it will pass the value of the "missing
argument". (which is different than simply being missing!)

If an argument x is missing _with_a default, then missing(x) is still true,
but if you pass x to another function, the default value is passed, not the
missing argument symbol.

If you add default arguments to your example, you'll see this effect:

f1 <- function(x, y, z){
   if(missing(x))
     cat("f1: x is missing\n")
   if(missing(y))
     cat("f1: y is missing\n")
}

f2 <- function(x, y, z){
   if(missing(z))
     cat("f2: z is missing\n")
   f1(x, y)
}

f2()

prints

f2: z is missing

The intersection of default values, and the representation of missing
without a default as a symbol yields some unexpected and complex behaviors.
Here are a few more fun examples:
https://github.com/bedatadriven/renjin/blob/master/tests/src/test/R/test.missing.R

Best,
Alex



On Tue, Oct 1, 2019, 10:27 Duncan Murdoch <[hidden email]> wrote:

>
> There's a StackOverflow question
> https://stackoverflow.com/q/22024082/2554330 that references this text
> from ?missing:
>
> "Currently missing can only be used in the immediate body of the
> function that defines the argument, not in the body of a nested function
> or a local call. This may change in the future."
>
> Someone pointed out (in https://stackoverflow.com/a/58169498/2554330)
> that this isn't true in the examples they've tried:  missingness does
> get passed along.  This example shows it (this is slightly different
> than the SO example):
>
> f1 <- function(x, y, z){
>    if(missing(x))
>      cat("f1: x is missing\n")
>    if(missing(y))
>      cat("f1: y is missing\n")
> }
>
> f2 <- function(x, y, z){
>    if(missing(z))
>      cat("f2: z is missing\n")
>    f1(x, y)
> }
>
> f2()
>
> which produces
>
> f2: z is missing
> f1: x is missing
> f1: y is missing
>
> Is the documentation out of date?  That quote appears to have been
> written in 2002.
>
> Duncan Murdoch
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Is missingness always passed on?

R devel mailing list
The updated example was meant to read:

f1 <- function(x = NULL, y = NULL, z = NULL){
  if(missing(x))
    cat("f1: x is missing\n")
  if(missing(y))
    cat("f1: y is missing\n")
}

f2 <- function(x = NULL, y = NULL, z = NULL){
  if(missing(z))
    cat("f2: z is missing\n")
  f1(x, y)
}

f2()

Alex

On Tue, Oct 1, 2019 at 10:37 AM Bertram, Alexander <[hidden email]>
wrote:

> There is "missing with default" and "missing without default".
>
> If an argument x is missing without a default, then missing(x) is true, if
> you pass x to another function, it will pass the value of the "missing
> argument". (which is different than simply being missing!)
>
> If an argument x is missing _with_a default, then missing(x) is still
> true, but if you pass x to another function, the default value is passed,
> not the missing argument symbol.
>
> If you add default arguments to your example, you'll see this effect:
>
> f1 <- function(x, y, z){
>    if(missing(x))
>      cat("f1: x is missing\n")
>    if(missing(y))
>      cat("f1: y is missing\n")
> }
>
> f2 <- function(x, y, z){
>    if(missing(z))
>      cat("f2: z is missing\n")
>    f1(x, y)
> }
>
> f2()
>
> prints
>
> f2: z is missing
>
> The intersection of default values, and the representation of missing
> without a default as a symbol yields some unexpected and complex behaviors.
> Here are a few more fun examples:
>
> https://github.com/bedatadriven/renjin/blob/master/tests/src/test/R/test.missing.R
>
> Best,
> Alex
>
>
>
> On Tue, Oct 1, 2019, 10:27 Duncan Murdoch <[hidden email]>
> wrote:
>
>>
>> There's a StackOverflow question
>> https://stackoverflow.com/q/22024082/2554330 that references this text
>> from ?missing:
>>
>> "Currently missing can only be used in the immediate body of the
>> function that defines the argument, not in the body of a nested function
>> or a local call. This may change in the future."
>>
>> Someone pointed out (in https://stackoverflow.com/a/58169498/2554330)
>> that this isn't true in the examples they've tried:  missingness does
>> get passed along.  This example shows it (this is slightly different
>> than the SO example):
>>
>> f1 <- function(x, y, z){
>>    if(missing(x))
>>      cat("f1: x is missing\n")
>>    if(missing(y))
>>      cat("f1: y is missing\n")
>> }
>>
>> f2 <- function(x, y, z){
>>    if(missing(z))
>>      cat("f2: z is missing\n")
>>    f1(x, y)
>> }
>>
>> f2()
>>
>> which produces
>>
>> f2: z is missing
>> f1: x is missing
>> f1: y is missing
>>
>> Is the documentation out of date?  That quote appears to have been
>> written in 2002.
>>
>> Duncan Murdoch
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>

--
Alexander Bertram
Technical Director
*BeDataDriven BV*

Web: http://bedatadriven.com
Email: [hidden email]
Tel. Nederlands: +31(0)647205388
Skype: akbertram

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Is missingness always passed on?

Serguei Sokol
In reply to this post by Duncan Murdoch-2
Le 30/09/2019 à 16:17, Duncan Murdoch a écrit :

>
> There's a StackOverflow question
> https://stackoverflow.com/q/22024082/2554330 that references this text
> from ?missing:
>
> "Currently missing can only be used in the immediate body of the
> function that defines the argument, not in the body of a nested
> function or a local call. This may change in the future."
>
> Someone pointed out (in https://stackoverflow.com/a/58169498/2554330)
> that this isn't true in the examples they've tried:  missingness does
> get passed along.  This example shows it (this is slightly different
> than the SO example):
>
> f1 <- function(x, y, z){
>   if(missing(x))
>     cat("f1: x is missing\n")
>   if(missing(y))
>     cat("f1: y is missing\n")
> }
>
> f2 <- function(x, y, z){
>   if(missing(z))
>     cat("f2: z is missing\n")
>   f1(x, y)
> }
>
> f2()
>
> which produces
>
> f2: z is missing
> f1: x is missing
> f1: y is missing
>
> Is the documentation out of date?  That quote appears to have been
> written in 2002.
Er, as far  as I understand the cited doc, it correctly describes what
happened in your example: missing() is not working in a local call (here
f1(x,y)).
In fact, what missing() of f1 is reporting it is still the situation of
f2() call (i.e. immediate body of the function). See

f2(y=1)

produces

f2: z is missing
f1: x is missing

(the line about y missing disappeared from f1(x,y) call, what needed to
be demonstrated).

Best,
Serguei.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Is missingness always passed on?

Duncan Murdoch-2
On 01/10/2019 4:58 a.m., Serguei Sokol wrote:

> Le 30/09/2019 à 16:17, Duncan Murdoch a écrit :
>>
>> There's a StackOverflow question
>> https://stackoverflow.com/q/22024082/2554330 that references this text
>> from ?missing:
>>
>> "Currently missing can only be used in the immediate body of the
>> function that defines the argument, not in the body of a nested
>> function or a local call. This may change in the future."
>>
>> Someone pointed out (in https://stackoverflow.com/a/58169498/2554330)
>> that this isn't true in the examples they've tried:  missingness does
>> get passed along.  This example shows it (this is slightly different
>> than the SO example):
>>
>> f1 <- function(x, y, z){
>>    if(missing(x))
>>      cat("f1: x is missing\n")
>>    if(missing(y))
>>      cat("f1: y is missing\n")
>> }
>>
>> f2 <- function(x, y, z){
>>    if(missing(z))
>>      cat("f2: z is missing\n")
>>    f1(x, y)
>> }
>>
>> f2()
>>
>> which produces
>>
>> f2: z is missing
>> f1: x is missing
>> f1: y is missing
>>
>> Is the documentation out of date?  That quote appears to have been
>> written in 2002.
> Er, as far  as I understand the cited doc, it correctly describes what
> happened in your example: missing() is not working in a local call (here
> f1(x,y)).
> In fact, what missing() of f1 is reporting it is still the situation of
> f2() call (i.e. immediate body of the function). See
>
> f2(y=1)
>
> produces
>
> f2: z is missing
> f1: x is missing
>
> (the line about y missing disappeared from f1(x,y) call, what needed to
> be demonstrated).

Yes, that's a possible interpretation.  Another one is that missing
should fail in this example:

f2 <- function(z){
    f1 <- function(){
      if(missing(z))
        cat("f1: z is missing\n")
    }
    f1()
}

and it does:

 > f2()
Error in missing(z) (from #3) : 'missing' can only be used for arguments

Here missing() is appearing in a nested function.  I'm really not sure
which is the intended meaning of that paragraph:  what exactly is a
"local call"?

Duncan Murdoch

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Is missingness always passed on?

Serguei Sokol
In reply to this post by Serguei Sokol
Le 01/10/2019 à 10:58, Serguei Sokol a écrit :

> Le 30/09/2019 à 16:17, Duncan Murdoch a écrit :
>>
>> There's a StackOverflow question
>> https://stackoverflow.com/q/22024082/2554330 that references this
>> text from ?missing:
>>
>> "Currently missing can only be used in the immediate body of the
>> function that defines the argument, not in the body of a nested
>> function or a local call. This may change in the future."
>>
>> Someone pointed out (in https://stackoverflow.com/a/58169498/2554330)
>> that this isn't true in the examples they've tried:  missingness does
>> get passed along.  This example shows it (this is slightly different
>> than the SO example):
>>
>> f1 <- function(x, y, z){
>>   if(missing(x))
>>     cat("f1: x is missing\n")
>>   if(missing(y))
>>     cat("f1: y is missing\n")
>> }
>>
>> f2 <- function(x, y, z){
>>   if(missing(z))
>>     cat("f2: z is missing\n")
>>   f1(x, y)
>> }
>>
>> f2()
>>
>> which produces
>>
>> f2: z is missing
>> f1: x is missing
>> f1: y is missing
>>
>> Is the documentation out of date?  That quote appears to have been
>> written in 2002.
> Er, as far  as I understand the cited doc, it correctly describes what
> happened in your example: missing() is not working in a local call
> (here f1(x,y)).
> In fact, what missing() of f1 is reporting it is still the situation
> of f2() call (i.e. immediate body of the function). See
>
> f2(y=1)
>
> produces
>
> f2: z is missing
> f1: x is missing
>
> (the line about y missing disappeared from f1(x,y) call, what needed
> to be demonstrated).
Re-er, it seem that I was a little bit to fast in my conclusion. If we
modify f2 to be

f2 <- function(x, y, z){
   if(missing(z))
     cat("f2: z is missing\n")
   f1(x=1, y)
}

then f2() call gives

f2: z is missing
f1: y is missing

i.e. missing() of f1(x=1,y) call is reporting its own situation, not
those of f2(). And the missingess of y seems to be inherited from f2() call.
Sorry to be hasty.

Serguei.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel