Unexpected argument-matching when some are missing

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

Unexpected argument-matching when some are missing

Emil
When trying out some variations with `[.data.frame` I noticed some (to me) odd behaviour, which I found out has nothing to do with `[.data.frame`, but rather with the way arguments are matched, when mixing named/unnamed and missing/non-missing arguments. Consider the following example:

 

myfun <- function(x,y,z) {

  print(match.call())

  cat('x=',if(missing(x)) 'missing' else x, '\n')

  cat('y=',if(missing(y)) 'missing' else y, '\n')

  cat('z=',if(missing(z)) 'missing' else z, '\n')

}

myfun(x=, y=, "z's value")

 

gives:

 

# myfun(x = "z's value")

# x= z's value

# y= missing

# z= missing

 

This seems very counterintuitive to me, I expect the arguments x and y to be missing, and z to get “z’s value”.

When I call myfun(,y=,"z's value"), x is missing, and y gets “z’s value”.

Are my expectations wrong or is this a bug? And if my expectations are wrong, where can I find more information on argument-matching?

My gut-feeling says to call this a bug, but then I’m surprised no-one else has encountered it before.

 

And I don’t have multiple installations to work from, so could somebody else confirm this (if it’s not my expectations that are wrong) for R-devel/other R-versions/other platforms?

My setup: R 3.5.1, MacOS 10.13.6, both Rstudio 1.1.453 and R --vanilla from Bash

 

Best regards,

Emil Bode


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

Re: Unexpected argument-matching when some are missing

Ista Zahn
On Thu, Nov 29, 2018 at 5:09 AM Emil Bode <[hidden email]> wrote:

>
> When trying out some variations with `[.data.frame` I noticed some (to me) odd behaviour, which I found out has nothing to do with `[.data.frame`, but rather with the way arguments are matched, when mixing named/unnamed and missing/non-missing arguments. Consider the following example:
>
>
>
> myfun <- function(x,y,z) {
>
>   print(match.call())
>
>   cat('x=',if(missing(x)) 'missing' else x, '\n')
>
>   cat('y=',if(missing(y)) 'missing' else y, '\n')
>
>   cat('z=',if(missing(z)) 'missing' else z, '\n')
>
> }
>
> myfun(x=, y=, "z's value")
>
>
>
> gives:
>
>
>
> # myfun(x = "z's value")
>
> # x= z's value
>
> # y= missing
>
> # z= missing
>
>
>
> This seems very counterintuitive to me, I expect the arguments x and y to be missing, and z to get “z’s value”.

Interesting. I would expect it to throw an error, since "x=" is not
syntactically complete. What does "x=" mean anyway? It looks like R
interprets it as "x was not set to anything, i.e., is missing". That
seems reasonable, though I think the example itself is pathological
and would prefer that it produced an error.

--Ista

>
> When I call myfun(,y=,"z's value"), x is missing, and y gets “z’s value”.
>
> Are my expectations wrong or is this a bug? And if my expectations are wrong, where can I find more information on argument-matching?
>
> My gut-feeling says to call this a bug, but then I’m surprised no-one else has encountered it before.
>
>
>
> And I don’t have multiple installations to work from, so could somebody else confirm this (if it’s not my expectations that are wrong) for R-devel/other R-versions/other platforms?
>
> My setup: R 3.5.1, MacOS 10.13.6, both Rstudio 1.1.453 and R --vanilla from Bash
>
>
>
> Best regards,
>
> Emil Bode
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

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

Re: Unexpected argument-matching when some are missing

S Ellison-2
In reply to this post by Emil
> When trying out some variations with `[.data.frame` I noticed some (to me)
> odd behaviour,

Not just in 'myfun' ...

plot(x=1:10, y=)
plot(x=1:10, y=, 10:1)

In both cases, 'y=' is ignored. In the first, the plot is for y=NULL (so not 'missing' y)
In the second case, 10:1 is positionally matched to y despite the intervening 'missing' 'y='

So it isn't just 'missing'; it's 'not there at all'

Steve E

> -----Original Message-----
> From: R-devel [mailto:[hidden email]] On Behalf Of Emil
> Bode
> Sent: 29 November 2018 10:09
> To: [hidden email]
> Subject: [Rd] Unexpected argument-matching when some are missing
>
> When trying out some variations with `[.data.frame` I noticed some (to me)
> odd behaviour, which I found out has nothing to do with `[.data.frame`, but
> rather with the way arguments are matched, when mixing named/unnamed
> and missing/non-missing arguments. Consider the following example:
>
>
>
> myfun <- function(x,y,z) {
>
>   print(match.call())
>
>   cat('x=',if(missing(x)) 'missing' else x, '\n')
>
>   cat('y=',if(missing(y)) 'missing' else y, '\n')
>
>   cat('z=',if(missing(z)) 'missing' else z, '\n')
>
> }
>
> myfun(x=, y=, "z's value")
>
>
>
> gives:
>
>
>
> # myfun(x = "z's value")
>
> # x= z's value
>
> # y= missing
>
> # z= missing
>
>
>
> This seems very counterintuitive to me, I expect the arguments x and y to be
> missing, and z to get “z’s value”.
>
> When I call myfun(,y=,"z's value"), x is missing, and y gets “z’s value”.
>
> Are my expectations wrong or is this a bug? And if my expectations are
> wrong, where can I find more information on argument-matching?
>
> My gut-feeling says to call this a bug, but then I’m surprised no-one else has
> encountered it before.
>
>
>
> And I don’t have multiple installations to work from, so could somebody else
> confirm this (if it’s not my expectations that are wrong) for R-devel/other R-
> versions/other platforms?
>
> My setup: R 3.5.1, MacOS 10.13.6, both Rstudio 1.1.453 and R --vanilla from
> Bash
>
>
>
> Best regards,
>
> Emil Bode



*******************************************************************
This email and any attachments are confidential. Any use, copying or
disclosure other than by the intended recipient is unauthorised. If
you have received this message in error, please notify the sender
immediately via +44(0)20 8943 7000 or notify [hidden email]
and delete this message and any copies from your computer and network.
LGC Limited. Registered in England 2991879.
Registered office: Queens Road, Teddington, Middlesex, TW11 0LY, UK
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected argument-matching when some are missing

Ista Zahn
On Thu, Nov 29, 2018 at 10:51 AM S Ellison <[hidden email]> wrote:

>
> > When trying out some variations with `[.data.frame` I noticed some (to me)
> > odd behaviour,
>
> Not just in 'myfun' ...
>
> plot(x=1:10, y=)
> plot(x=1:10, y=, 10:1)
>
> In both cases, 'y=' is ignored. In the first, the plot is for y=NULL (so not 'missing' y)
> In the second case, 10:1 is positionally matched to y despite the intervening 'missing' 'y='
>
> So it isn't just 'missing'; it's 'not there at all'

What exactly is the difference between "missing" and "not there at all"?

--Ista

>
> Steve E
>
> > -----Original Message-----
> > From: R-devel [mailto:[hidden email]] On Behalf Of Emil
> > Bode
> > Sent: 29 November 2018 10:09
> > To: [hidden email]
> > Subject: [Rd] Unexpected argument-matching when some are missing
> >
> > When trying out some variations with `[.data.frame` I noticed some (to me)
> > odd behaviour, which I found out has nothing to do with `[.data.frame`, but
> > rather with the way arguments are matched, when mixing named/unnamed
> > and missing/non-missing arguments. Consider the following example:
> >
> >
> >
> > myfun <- function(x,y,z) {
> >
> >   print(match.call())
> >
> >   cat('x=',if(missing(x)) 'missing' else x, '\n')
> >
> >   cat('y=',if(missing(y)) 'missing' else y, '\n')
> >
> >   cat('z=',if(missing(z)) 'missing' else z, '\n')
> >
> > }
> >
> > myfun(x=, y=, "z's value")
> >
> >
> >
> > gives:
> >
> >
> >
> > # myfun(x = "z's value")
> >
> > # x= z's value
> >
> > # y= missing
> >
> > # z= missing
> >
> >
> >
> > This seems very counterintuitive to me, I expect the arguments x and y to be
> > missing, and z to get “z’s value”.
> >
> > When I call myfun(,y=,"z's value"), x is missing, and y gets “z’s value”.
> >
> > Are my expectations wrong or is this a bug? And if my expectations are
> > wrong, where can I find more information on argument-matching?
> >
> > My gut-feeling says to call this a bug, but then I’m surprised no-one else has
> > encountered it before.
> >
> >
> >
> > And I don’t have multiple installations to work from, so could somebody else
> > confirm this (if it’s not my expectations that are wrong) for R-devel/other R-
> > versions/other platforms?
> >
> > My setup: R 3.5.1, MacOS 10.13.6, both Rstudio 1.1.453 and R --vanilla from
> > Bash
> >
> >
> >
> > Best regards,
> >
> > Emil Bode
>
>
>
> *******************************************************************
> This email and any attachments are confidential. Any u...{{dropped:11}}

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

Re: Unexpected argument-matching when some are missing

Emil
In reply to this post by Ista Zahn
Well, I did mean it as "missing".
To me, it felt just as natural as providing an empty index for subsetting (e.g. some.data.frame[,,drop=FALSE])
I can't think of a whole lot of other uses than subsetting, but I think this issue may be mostly important when you're not entirely sure what a call is going to end up, when passing along arguments, or when calling an unknown function (as in variants of the apply-family, where you provide a function as an argument).
Or what happens if I use do.call(FUN, args=MyNamedList)? I have a bit more extensive example further down where you can more clearly see the unexpected output.

But the problem is that R does NOT treat it as simply "missing". That would have been reasonable, but instead, as in the example in my previous mail,
myfun(x=, y=, "z's value") means x is assigned "z's value", and y and z are seen as missing. Which is not at all what I was expecting.

And is also not consistent with other behaviour, as myfun(,,"z's value") and myfun(x=, y=, z="z's value") do work as expected (at least what I was expecting)

The extensice example:
Suppose I want to write a function that selects data from some external source. In order to do this, we put the data in its own environment, where we look for variables called "df", "rows", "cols" and "drop", and use these to make a selection. I write this function:

doselect <- function(env) {
  do.call(`[.data.frame`, list(env$df, if(!is.null(env$rows)) env$rows, if(!is.null(env$cols)) env$cols, drop=if(!is.null(env$drop)) env$drop))
}

It works for this code:
myenv <- new.env()
assign('df', data.frame(a=1:2, b=3:4), myenv, inherits=FALSE)
assign('rows', 1, myenv, inherits=FALSE) # Code breaks if we don't have this line
assign('cols', 1, myenv, inherits=FALSE) # Code breaks if we don't have this line
assign('drop', FALSE, myenv, inherits=FALSE)
doselect(myenv)

But if we don't assign "rows" and/or "cols", the variable "drop" is inserted in the place of the first unnamed variable, so the result is the same as if calling
df[FALSE,,]:
[1] a b
<0 rows> (or 0-length row.names)

What I did expect was the same result as df[,,FALSE], i.e. the full data.frame. Of course I can rewrite the function "doselect", but I think my current call is how most people would write it (even though I admit the example in its entirety is far-fetched)


Best regards,
Emil Bode
 

On 29/11/2018, 14:58, "Ista Zahn" <[hidden email]> wrote:

    On Thu, Nov 29, 2018 at 5:09 AM Emil Bode <[hidden email]> wrote:
    >
    > When trying out some variations with `[.data.frame` I noticed some (to me) odd behaviour, which I found out has nothing to do with `[.data.frame`, but rather with the way arguments are matched, when mixing named/unnamed and missing/non-missing arguments. Consider the following example:
    >
    > myfun <- function(x,y,z) {
    >   print(match.call())
    >   cat('x=',if(missing(x)) 'missing' else x, '\n')
    >   cat('y=',if(missing(y)) 'missing' else y, '\n')
    >   cat('z=',if(missing(z)) 'missing' else z, '\n')
    > }
    > myfun(x=, y=, "z's value")
    >
    > gives:
    >
    > # myfun(x = "z's value")
    > # x= z's value
    > # y= missing
    > # z= missing
    >
    > This seems very counterintuitive to me, I expect the arguments x and y to be missing, and z to get “z’s value”.
   
    Interesting. I would expect it to throw an error, since "x=" is not
    syntactically complete. What does "x=" mean anyway? It looks like R
    interprets it as "x was not set to anything, i.e., is missing". That
    seems reasonable, though I think the example itself is pathological
    and would prefer that it produced an error.
   
    --Ista
    >
    > When I call myfun(,y=,"z's value"), x is missing, and y gets “z’s value”.
   > Are my expectations wrong or is this a bug? And if my expectations are wrong, where can I find more information on argument-matching?
   > My gut-feeling says to call this a bug, but then I’m surprised no-one else has encountered it before.
   >
    > And I don’t have multiple installations to work from, so could somebody else confirm this (if it’s not my expectations that are wrong) for R-devel/other R-versions/other platforms?
    >
    > My setup: R 3.5.1, MacOS 10.13.6, both Rstudio 1.1.453 and R --vanilla from Bash
    >
    > Best regards,
    >
    > Emil Bode
    >
    > ______________________________________________
    > [hidden email] mailing list
    > https://stat.ethz.ch/mailman/listinfo/r-devel
   

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

Re: Unexpected argument-matching when some are missing

S Ellison-2
In reply to this post by Ista Zahn

> > plot(x=1:10, y=)
> > plot(x=1:10, y=, 10:1)
> >
> > In both cases, 'y=' is ignored. In the first, the plot is for y=NULL (so not
> 'missing' y)
> > In the second case, 10:1 is positionally matched to y despite the intervening
> 'missing' 'y='
> >
> > So it isn't just 'missing'; it's 'not there at all'
>
> What exactly is the difference between "missing" and "not there at all"?

A "missing argument" in R means that an argument with no default value was omitted from the call, and that is what I meant by "missing".
But that is not what is happening here. I was talking about "y=" apparently being treated as not present in the call, rather than the argument y being treated as a missing argument.  

In these examples, plot.default has a default value for y (NULL) so y can never be "missing" in the sense of the 'missing argument' error (compare what happens with plot(y=1:10), which reports x as 'missing').
In the first example, y was (from the plot behaviour) taken as NULL - the default - so was not considered a missing argument. In the second, it was taken as 10:1 - again, non-missing, despite 10:1 being in the normal position for the (character) argument "type".
But neither call did anything at all with "y=". Instead, the behaviour is consistent with what would have happened if 'y=' were "not present at all" when counting position or named argument list, rather than if 'y' were an absent required argument.
It _looks_ as if the initial call parsing silently ignored the malformed expression "y=" before any argument matching - positional or by name - takes place.

But I'm thinking that it'll take an R-core guru to explain what's going on here, so I was going to wait and see.

Steve Ellison



*******************************************************************
This email and any attachments are confidential. Any use, copying or
disclosure other than by the intended recipient is unauthorised. If
you have received this message in error, please notify the sender
immediately via +44(0)20 8943 7000 or notify [hidden email]
and delete this message and any copies from your computer and network.
LGC Limited. Registered in England 2991879.
Registered office: Queens Road, Teddington, Middlesex, TW11 0LY, UK
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected argument-matching when some are missing

Ista Zahn
On Thu, Nov 29, 2018 at 1:10 PM S Ellison <[hidden email]> wrote:

>
>
> > > plot(x=1:10, y=)
> > > plot(x=1:10, y=, 10:1)
> > >
> > > In both cases, 'y=' is ignored. In the first, the plot is for y=NULL (so not
> > 'missing' y)
> > > In the second case, 10:1 is positionally matched to y despite the intervening
> > 'missing' 'y='
> > >
> > > So it isn't just 'missing'; it's 'not there at all'
> >
> > What exactly is the difference between "missing" and "not there at all"?
>
> A "missing argument" in R means that an argument with no default value was omitted from the call, and that is what I meant by "missing".
> But that is not what is happening here. I was talking about "y=" apparently being treated as not present in the call, rather than the argument y being treated as a missing argument.
>
> In these examples, plot.default has a default value for y (NULL) so y can never be "missing" in the sense of the 'missing argument' error (compare what happens with plot(y=1:10), which reports x as 'missing').
> In the first example, y was (from the plot behaviour) taken as NULL - the default - so was not considered a missing argument. In the second, it was taken as 10:1 - again, non-missing, despite 10:1 being in the normal position for the (character) argument "type".
> But neither call did anything at all with "y=". Instead, the behaviour is consistent with what would have happened if 'y=' were "not present at all" when counting position or named argument list, rather than if 'y' were an absent required argument.
> It _looks_ as if the initial call parsing silently ignored the malformed expression "y=" before any argument matching - positional or by name - takes place.

Yes, I think all of that is correct. But y _is_ missing in this sense:

> debug(plot)
> plot(1:10, y=)
debugging in: plot(1:10, y = )
debug: UseMethod("plot")
Browse[2]> missing(y)
[1] TRUE

though this does not explain the behavior since

> plot( , , "l")
debugging in: plot(, , "l")
debug: UseMethod("plot")
Browse[2]> missing(y)
[1] TRUE

--Ista
>
> But I'm thinking that it'll take an R-core guru to explain what's going on here, so I was going to wait and see.
>
> Steve Ellison
>
>
>
> *******************************************************************
> This email and any attachments are confidential. Any u...{{dropped:8}}

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

Re: Unexpected argument-matching when some are missing

Emil
In reply to this post by S Ellison-2
It looks like you're right that somewhere in (presumably) match.call, the named, empty arguments are removed, such that the call plot(x=1:10, y=, 10:1) is translated to plot(x=1:10, 10:1).
But I would have expected it to be the same as plot(x=1:10, , 10:1) (note the ", ,"), which gives an error (10:1 is not a valid plot-type). In this case you get an error straightaway, I find this more interesting:
> options(warn=-1)
> plot(x=1, y=, 'p', ylim=c(0,10))
> plot(x=1, , 'p', ylim=c(0,10))
Both valid (no errors), albeit strange calls, but I'd say the first call is better code, it's clearer you intend to not give any value for y. But exactly this one gives unexpected results: it tries to plot at position (1, 'p'), or (1, NA).

And the behaviour as it is gives rise to some strange inconsistencies. I have gathered some examples below (at the very bottom of the thread, as it got quite extensive), where some variations are surprisingly different from each other.
There are also some issues when using data.frame(...)[i=, j=,...], but at least here you are warned about naming i and j.
But basically, it means any function where arguments like fun(,,) are a valid possibility should throw the same warning, e.g. any R-code replacement of [.matrix or [.array, or as in my examples, for data.table (and related structures)

On 29/11/2018, 19:10, "S Ellison" <[hidden email]> wrote:

   
    > > plot(x=1:10, y=)
    > > plot(x=1:10, y=, 10:1)
    > >
    > > In both cases, 'y=' is ignored. In the first, the plot is for y=NULL (so not
    > 'missing' y)
    > > In the second case, 10:1 is positionally matched to y despite the intervening
    > 'missing' 'y='
    > >
    > > So it isn't just 'missing'; it's 'not there at all'
    >
    > What exactly is the difference between "missing" and "not there at all"?
   
    A "missing argument" in R means that an argument with no default value was omitted from the call, and that is what I meant by "missing".
    But that is not what is happening here. I was talking about "y=" apparently being treated as not present in the call, rather than the argument y being treated as a missing argument.  
   
    In these examples, plot.default has a default value for y (NULL) so y can never be "missing" in the sense of the 'missing argument' error (compare what happens with plot(y=1:10), which reports x as 'missing').
    In the first example, y was (from the plot behaviour) taken as NULL - the default - so was not considered a missing argument. In the second, it was taken as 10:1 - again, non-missing, despite 10:1 being in the normal position for the (character) argument "type".
    But neither call did anything at all with "y=". Instead, the behaviour is consistent with what would have happened if 'y=' were "not present at all" when counting position or named argument list, rather than if 'y' were an absent required argument.
    It _looks_ as if the initial call parsing silently ignored the malformed expression "y=" before any argument matching - positional or by name - takes place.
   
    But I'm thinking that it'll take an R-core guru to explain what's going on here, so I was going to wait and see.
   
    Steve Ellison
   

Exampled if what I (Emil) found odd:
---------------------------------------------------------------------------------------------------------------------------------------
> library(data.table)
> options(warn=1) # Or 2
> data.table(a=1:2, b=3:4)[1] # As expected
   a b
1: 1 3
> data.table(a=1:2, b=3:4)[, 1] # As expected
   a
1: 1
2: 2
> data.table(a=1:2, b=3:4)[i=, 1] # Huh? We get the first row
   a b
1: 1 3
> data.table(a=1:2, b=3:4)[, 1, 'a'] # As expected
   a V1
1: 1  1
2: 2  1
> data.table(a=1:2, b=3:4)[i=, 1, 'a'] # I would have expected the same result, and definitely more than 1 value
   a
1: 1
> data.table(a=1:2, b=3:4)[i=, 1, by='a'] # And this doesn't work?
Error in `[.data.table`(data.table(a = 1:2, b = 3:4), i = , 1, by = "a") :
  'by' or 'keyby' is supplied but not j
> myfun <- function(x,y,z) {
+   print(match.call())
+   cat('nargs: ', nargs(), '\n')
+   cat('x=',if(missing(x)) 'missing' else x, '\n')
+   cat('y=',if(missing(y)) 'missing' else y, '\n')
+   cat('z=',if(missing(z)) 'missing' else z, '\n')
+ }
> myfun(x=, y=, , , "z's value") # 5 arguments??
myfun(z = "z's value")
nargs:  5
x= missing
y= missing
z= z's value
> myfun(x=, y=, , , "z's value", , ) # But any more are not allowed
Error in myfun(x = , y = , , , "z's value", , ) :
  unused arguments (alist(, ))
> myfun(x2=, y=, "z's value") # And named arguments are ignored, but the names have to be to existing argument-names
Error in myfun(x2 = , y = , "z's value") : unused argument (alist(x2 = ))
> myfun(x=, x=, , "z's value") # And naming it multiple times also gives an error
Error in myfun(x = , x = , , "z's value") :
  formal argument "x" matched by multiple actual arguments
> myfun(y=, , "z's value", x=3) # Having fun with obfuscation, is this call backwards and forwards compatible?
myfun(x = 3, z = "z's value")
nargs:  4
x= 3
y= missing
z= z's value
> myfun(y=rlang::missing_arg(), , "z's value", x=3)
Error in myfun(y = rlang::missing_arg(), , "z's value", x = 3) :
  unused argument ("z's value")
> myfun(y=rlang::missing_arg(), z=, "z's value", x=3) # Now with a named empty argument
myfun(x = 3, y = rlang::missing_arg(), z = "z's value")
nargs:  4
x= 3
y=  
z= z's value
> myfun(y=rlang::missing_arg(), z= "z's value", x=3) # Just a comma removed: same match.call(), different nargs()
myfun(x = 3, y = rlang::missing_arg(), z = "z's value")
nargs:  3
x= 3
y=  
z= z's value


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

Re: Unexpected argument-matching when some are missing

S Ellison-2
In reply to this post by Ista Zahn
> Yes, I think all of that is correct. But y _is_ missing in this sense:
> > plot(1:10, y=)
> > ...
> Browse[2]> missing(y)

Although I said what I meant by 'missing' vs 'not present', it wasn't exactly what missing() means. My bad.
missing() returns TRUE if an argument is not specified in the call _whether or not_ it has a default, hence the behaviour of missing(y) in debug(plot).

But we can easily find out whether a default has been assigned:
plot(1:10, y=, type=)
Browse[2]> y
NULL
Browse[2]> type
"p"

... which is consistent with silent omission of 'y=' and 'type='


Still waiting for a guru...

Steve E



*******************************************************************
This email and any attachments are confidential. Any use, copying or
disclosure other than by the intended recipient is unauthorised. If
you have received this message in error, please notify the sender
immediately via +44(0)20 8943 7000 or notify [hidden email]
and delete this message and any copies from your computer and network.
LGC Limited. Registered in England 2991879.
Registered office: Queens Road, Teddington, Middlesex, TW11 0LY, UK
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected argument-matching when some are missing

Emil
But the main point is where arguments are mixed together:

> debugonce(plot.default)
> plot(x=1:10, y=, 'l')
...
Browse[2]> missing(y)
[1] FALSE
Browse[2]> y
[1] "l"
Browse[2]> type
[1] "p"

I think that's what I fall over mostly: that named, empty arguments behave entirely different from omitting them (", ,")

And I definitely agree we need a guru to explain it all to us (

Cheers, Emil Bode


On 30/11/2018, 15:35, "S Ellison" <[hidden email]> wrote:

    > Yes, I think all of that is correct. But y _is_ missing in this sense:
    > > plot(1:10, y=)
    > > ...
    > Browse[2]> missing(y)
   
    Although I said what I meant by 'missing' vs 'not present', it wasn't exactly what missing() means. My bad.
    missing() returns TRUE if an argument is not specified in the call _whether or not_ it has a default, hence the behaviour of missing(y) in debug(plot).
   
    But we can easily find out whether a default has been assigned:
    plot(1:10, y=, type=)
    Browse[2]> y
    NULL
    Browse[2]> type
    "p"
   
    ... which is consistent with silent omission of 'y=' and 'type='
   
   
    Still waiting for a guru...
   
    Steve E
   
   
   
    *******************************************************************
    This email and any attachments are confidential. Any use, copying or
    disclosure other than by the intended recipient is unauthorised. If
    you have received this message in error, please notify the sender
    immediately via +44(0)20 8943 7000 or notify [hidden email]
    and delete this message and any copies from your computer and network.
    LGC Limited. Registered in England 2991879.
    Registered office: Queens Road, Teddington, Middlesex, TW11 0LY, UK
   

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

Re: Unexpected argument-matching when some are missing

Michael Lawrence-3
Argument matching is by name first, then the still missing arguments
are filled positionally. Unnamed missing arguments are thus left
missing. Does that help?

Michael
On Fri, Nov 30, 2018 at 8:18 AM Emil Bode <[hidden email]> wrote:

>
> But the main point is where arguments are mixed together:
>
> > debugonce(plot.default)
> > plot(x=1:10, y=, 'l')
> ...
> Browse[2]> missing(y)
> [1] FALSE
> Browse[2]> y
> [1] "l"
> Browse[2]> type
> [1] "p"
>
> I think that's what I fall over mostly: that named, empty arguments behave entirely different from omitting them (", ,")
>
> And I definitely agree we need a guru to explain it all to us (
>
> Cheers, Emil Bode
>
>
> On 30/11/2018, 15:35, "S Ellison" <[hidden email]> wrote:
>
>     > Yes, I think all of that is correct. But y _is_ missing in this sense:
>     > > plot(1:10, y=)
>     > > ...
>     > Browse[2]> missing(y)
>
>     Although I said what I meant by 'missing' vs 'not present', it wasn't exactly what missing() means. My bad.
>     missing() returns TRUE if an argument is not specified in the call _whether or not_ it has a default, hence the behaviour of missing(y) in debug(plot).
>
>     But we can easily find out whether a default has been assigned:
>     plot(1:10, y=, type=)
>     Browse[2]> y
>     NULL
>     Browse[2]> type
>     "p"
>
>     ... which is consistent with silent omission of 'y=' and 'type='
>
>
>     Still waiting for a guru...
>
>     Steve E
>
>
>
>     *******************************************************************
>     This email and any attachments are confidential. Any use, copying or
>     disclosure other than by the intended recipient is unauthorised. If
>     you have received this message in error, please notify the sender
>     immediately via +44(0)20 8943 7000 or notify [hidden email]
>     and delete this message and any copies from your computer and network.
>     LGC Limited. Registered in England 2991879.
>     Registered office: Queens Road, Teddington, Middlesex, TW11 0LY, UK
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

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

Re: Unexpected argument-matching when some are missing

Martin Maechler
>>>>> Michael Lawrence
>>>>>     on Fri, 30 Nov 2018 08:24:31 -0800 writes:

    > Argument matching is by name first, then the still missing
    > arguments are filled positionally. Unnamed missing
    > arguments are thus left missing. Does that help?

Thank you, Michael!
Unfortunately, it may not help sufficiently notably once this
thread will be forgotten, even though I had thought so exactly
as well.  Of course we two may find R's matching algorithm
entirely intuitive, but e.g., Ista expected R even "to throw an
error" in this case, and there are about 99% of R users less savvy than
him, so let me think loudly a bit further ...
IIUC, Emil's case is mostly about this

  > ff <- function(x,y,z,...) list(sysC=sys.call(), match=match.call())
  > str( ff(x=, z=pi, "foo") )
  List of 2
   $ sysC : language ff(x = , z = pi, "foo")
   $ match: language ff(x = "foo", z = pi)
  >

where the argument matching rule above would have suggested to him that the
matched call should have become
  ff(y = "foo", z = pi)  rather than
  ff(x = "foo", z = pi)

because he'd expected the empty 'x =' to be matched by name and
hence *not* be matched again later when all the missing
arguments are matched positionally in the end.
NB because of the rule Michael cited above *of course*,
", ," (in your example below) is not equivalent to
"y = ," because the former leads to positional matching at position 2.

Now R's matching argument algorithm has therefore been consistent with
the above simple matching rule ((which did not include the exact vs
partial matching but that was not the topic here anyway))
that had been documented as that forever and AFAIK the same as S had.

What may be possible (and suggested in this thread ?) would be
to start signalling a warning when named empty arguments (the
" y = , "  in the example) are matched(*), i.e., it would give a
warning in match.call() but not sys.call(), and hence utilities
such as  alist()  would continue to work unchanged.

I have no idea (and no time currently to investigate) if such
warnings would be too disruptive for the current R code base or not.

Martin

----
*) "matched" in that case effectively means "dropped" as we have
    seen in the examples.
   

    > On Fri, Nov 30, 2018 at 8:18 AM Emil Bode <[hidden email]> wrote:
    >>
    >> But the main point is where arguments are mixed together:
    >>
    >> > debugonce(plot.default)
    >> > plot(x=1:10, y=, 'l')
    >> ...
    >> Browse[2]> missing(y)
    >> [1] FALSE
    >> Browse[2]> y
    >> [1] "l"
    >> Browse[2]> type
    >> [1] "p"
    >>
    >> I think that's what I fall over mostly: that named, empty arguments behave entirely different from omitting them (", ,")
    >>
    >> And I definitely agree we need a guru to explain it all to us (
    >>
    >> Cheers, Emil Bode
    >>
    >>
    >> On 30/11/2018, 15:35, "S Ellison" <[hidden email]> wrote:
    >>
    >> > Yes, I think all of that is correct. But y _is_ missing in this sense:
    >> > > plot(1:10, y=)
    >> > > ...
    >> > Browse[2]> missing(y)
    >>
    >> Although I said what I meant by 'missing' vs 'not present', it wasn't exactly what missing() means. My bad.
    >> missing() returns TRUE if an argument is not specified in the call _whether or not_ it has a default, hence the behaviour of missing(y) in debug(plot).
    >>
    >> But we can easily find out whether a default has been assigned:
    >> plot(1:10, y=, type=)
    >> Browse[2]> y
    >> NULL
    >> Browse[2]> type
    >> "p"
    >>
    >> ... which is consistent with silent omission of 'y=' and 'type='
    >>
    >>
    >> Still waiting for a guru...
    >>
    >> Steve E

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

Re: Unexpected argument-matching when some are missing

Emil
Thanks as well!
I'm now getting how it's exactly matched, but it still "feels wrong".
Martins rewording is exactly what I meant/was concerned about.
My intuition would say that anyone using ff(x=, ...) would not intent x to be matched to something else, but maybe I'm overlooking certain cases.
Anyway, I agree that throwing a warning would probably be the best solution.
I don't exactly know how to test for compatibility for such changes (never really worked with CRAN/extensive testing), but if I can do something to help I'd be glad to.
And if it turns out to be too disruptive, maybe we can write Patrick Burns (the R-inferno) ; - )

Best regards,
Emil Bode
 
On 03/12/2018, 10:57, "Martin Maechler" <[hidden email]> wrote:

    >>>>> Michael Lawrence
    >>>>>     on Fri, 30 Nov 2018 08:24:31 -0800 writes:
   
        > Argument matching is by name first, then the still missing
        > arguments are filled positionally. Unnamed missing
        > arguments are thus left missing. Does that help?
   
    Thank you, Michael!
    Unfortunately, it may not help sufficiently notably once this
    thread will be forgotten, even though I had thought so exactly
    as well.  Of course we two may find R's matching algorithm
    entirely intuitive, but e.g., Ista expected R even "to throw an
    error" in this case, and there are about 99% of R users less savvy than
    him, so let me think loudly a bit further ...
    IIUC, Emil's case is mostly about this
   
      > ff <- function(x,y,z,...) list(sysC=sys.call(), match=match.call())
      > str( ff(x=, z=pi, "foo") )
      List of 2
       $ sysC : language ff(x = , z = pi, "foo")
       $ match: language ff(x = "foo", z = pi)
      >
   
    where the argument matching rule above would have suggested to him that the
    matched call should have become
      ff(y = "foo", z = pi)  rather than
      ff(x = "foo", z = pi)
   
    because he'd expected the empty 'x =' to be matched by name and
    hence *not* be matched again later when all the missing
    arguments are matched positionally in the end.
    NB because of the rule Michael cited above *of course*,
    ", ," (in your example below) is not equivalent to
    "y = ," because the former leads to positional matching at position 2.
   
    Now R's matching argument algorithm has therefore been consistent with
    the above simple matching rule ((which did not include the exact vs
    partial matching but that was not the topic here anyway))
    that had been documented as that forever and AFAIK the same as S had.
   
    What may be possible (and suggested in this thread ?) would be
    to start signalling a warning when named empty arguments (the
    " y = , "  in the example) are matched(*), i.e., it would give a
    warning in match.call() but not sys.call(), and hence utilities
    such as  alist()  would continue to work unchanged.
   
    I have no idea (and no time currently to investigate) if such
    warnings would be too disruptive for the current R code base or not.
   
    Martin
   
    ----
    *) "matched" in that case effectively means "dropped" as we have
        seen in the examples.
       
   
        > On Fri, Nov 30, 2018 at 8:18 AM Emil Bode <[hidden email]> wrote:
        >>
        >> But the main point is where arguments are mixed together:
        >>
        >> > debugonce(plot.default)
        >> > plot(x=1:10, y=, 'l')
        >> ...
        >> Browse[2]> missing(y)
        >> [1] FALSE
        >> Browse[2]> y
        >> [1] "l"
        >> Browse[2]> type
        >> [1] "p"
        >>
        >> I think that's what I fall over mostly: that named, empty arguments behave entirely different from omitting them (", ,")
        >>
        >> And I definitely agree we need a guru to explain it all to us (
        >>
        >> Cheers, Emil Bode
        >>
        >>
        >> On 30/11/2018, 15:35, "S Ellison" <[hidden email]> wrote:
        >>
        >> > Yes, I think all of that is correct. But y _is_ missing in this sense:
        >> > > plot(1:10, y=)
        >> > > ...
        >> > Browse[2]> missing(y)
        >>
        >> Although I said what I meant by 'missing' vs 'not present', it wasn't exactly what missing() means. My bad.
        >> missing() returns TRUE if an argument is not specified in the call _whether or not_ it has a default, hence the behaviour of missing(y) in debug(plot).
        >>
        >> But we can easily find out whether a default has been assigned:
        >> plot(1:10, y=, type=)
        >> Browse[2]> y
        >> NULL
        >> Browse[2]> type
        >> "p"
        >>
        >> ... which is consistent with silent omission of 'y=' and 'type='
        >>
        >>
        >> Still waiting for a guru...
        >>
        >> Steve E
     
   

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