Not sure if this belongs on r-help or r-package-devel; decided for the
latter as the question is mainly relevant when writing code to be used
by others.
The issue I run into is that I want to write a function similar to:
foo <- function(x, schema = schema(x)) {
if (is.null(schema)) stop("schema missing")
# ...
}
with 'schema()' something like (strongly simplified):
schema <- function(x) attr(x, "schema")
However using both the argument schema and calling the schema() function
in one of the default arguments is not allowed ans results in the
following somewhat cryptic error message:
Error in foo(1:3) :
promise already under evaluation: recursive default argument
reference or earlier problems?
I am looking for a clean solution to this. I can rename the argument or
function, but calling it something other than schema feels impractical
as both refer to the same thing (the schema of x). The best solution I
have come up with until now is to define a second function to be used in
default function arguments:
schema_ <- schema
foo <- function(x, schema = schema_(x)) {
if (is.null(schema)) stop("schema missing")
# ...
}
I guess another solution would be:
foo <- function(x, schema) {
if (missing(schema)) schema <- schema(x)
}
But then it is not clear for the user from the interface that the
'schema' argument can be omitted.
I am hoping some of you have other suggestions.
And, is this something that could be 'fixed' in the R-parser?
Thanks,
Jan
[R-pkg-devel] Using function with same name as argument as default argument
6 messages · Andrew Simmons, Ivan Krylov, Duncan Murdoch +1 more
Hello,
This isn't something that can be fixed in the parser. If an argument isn't
provided, its default value is evaluated inside the function, so it gives
you a loop where schema = schema(x), but then what's schema, it's
schema(x), thus the recursion error. you could do something like this:
foo <- function (x, schema = schema(x))
{
if (missing(schema)) {
rm(schema)
schema <- schema(x)
}
}
which, while kinda gross looking, means that schema = schema(x) can be
evaluated without causing a recursion error.
On Mon, Aug 8, 2022, 09:11 Jan van der Laan <rhelp at eoos.dds.nl> wrote:
Not sure if this belongs on r-help or r-package-devel; decided for the
latter as the question is mainly relevant when writing code to be used
by others.
The issue I run into is that I want to write a function similar to:
foo <- function(x, schema = schema(x)) {
if (is.null(schema)) stop("schema missing")
# ...
}
with 'schema()' something like (strongly simplified):
schema <- function(x) attr(x, "schema")
However using both the argument schema and calling the schema() function
in one of the default arguments is not allowed ans results in the
following somewhat cryptic error message:
Error in foo(1:3) :
promise already under evaluation: recursive default argument
reference or earlier problems?
I am looking for a clean solution to this. I can rename the argument or
function, but calling it something other than schema feels impractical
as both refer to the same thing (the schema of x). The best solution I
have come up with until now is to define a second function to be used in
default function arguments:
schema_ <- schema
foo <- function(x, schema = schema_(x)) {
if (is.null(schema)) stop("schema missing")
# ...
}
I guess another solution would be:
foo <- function(x, schema) {
if (missing(schema)) schema <- schema(x)
}
But then it is not clear for the user from the interface that the
'schema' argument can be omitted.
I am hoping some of you have other suggestions.
And, is this something that could be 'fixed' in the R-parser?
Thanks,
Jan
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
On Mon, 8 Aug 2022 15:10:37 +0200
Jan van der Laan <rhelp at eoos.dds.nl> wrote:
I guess another solution would be:
foo <- function(x, schema) {
if (missing(schema)) schema <- schema(x)
}
But then it is not clear for the user from the interface that the
'schema' argument can be omitted.
Here's a workaround that should work inside a package:
function(x, schema = mypackagename::schema(x))
For inline functions, this workaround is also possible, but I can only
think of an extremely ugly variant:
schema <- function(x) { force(x); 'schema' }
foo <- function(
x, schema = get('schema', parent.env(environment()))(x)
) { force(schema); 'foo' }
foo(1) # works
Best regards, Ivan
Hi Andrew and Ivan,
Thanks for the suggestion. Both are good suggestions; better than what I
have.
Andrews solution:
> foo <- function (x, schema = schema(x))
> {
> if (missing(schema)) {
> rm(schema)
> schema <- schema(x)
> }
> }
Ivans:
> function(x, schema = mypackagename::schema(x))
Both would work in this case. Ivans is a bit cleaner/simpler; Andrews
appears simpler from a user perspective. Not sure yet which one I will
use; I am currently leaning towards Ivans solution.
Thanks!
Jan
On 08-08-2022 15:42, Andrew Simmons wrote:
Hello,
This isn't something that can be fixed in the parser. If an argument
isn't provided, its default value is evaluated inside the function, so
it gives you a loop where schema = schema(x), but then what's schema,
it's schema(x), thus the recursion error. you could do something like this:
foo <- function (x, schema = schema(x))
{
? ? if (missing(schema)) {
? ? ? ? rm(schema)
? ? ? ? schema <- schema(x)
? ? }
}
which, while kinda gross looking, means that schema = schema(x) can be
evaluated without causing a recursion error.
On Mon, Aug 8, 2022, 09:11 Jan van der Laan <rhelp at eoos.dds.nl
<mailto:rhelp at eoos.dds.nl>> wrote:
Not sure if this belongs on r-help or r-package-devel; decided for the
latter as the question is mainly relevant when writing code to be used
by others.
The issue I run into is that I want to write a function similar to:
foo <- function(x, schema = schema(x)) {
? ?if (is.null(schema)) stop("schema missing")
? ?# ...
}
with 'schema()' something like (strongly simplified):
schema <- function(x) attr(x, "schema")
However using both the argument schema and calling the schema()
function
in one of the default arguments is not allowed ans results in the
following somewhat cryptic error message:
Error in foo(1:3) :
? ?promise already under evaluation: recursive default argument
reference or earlier problems?
I am looking for a clean solution to this. I can rename the argument or
function, but calling it something other than schema feels impractical
as both refer to the same thing (the schema of x). The best solution I
have come up with until now is to define a second function to be
used in
default function arguments:
schema_ <- schema
foo <- function(x, schema = schema_(x)) {
? ?if (is.null(schema)) stop("schema missing")
? ?# ...
}
I guess another solution would be:
foo <- function(x, schema) {
? ?if (missing(schema)) schema <- schema(x)
}
But then it is not clear for the user from the interface that the
'schema' argument can be omitted.
I am hoping some of you have other suggestions.
And, is this something that could be 'fixed' in the R-parser?
Thanks,
Jan
______________________________________________
R-package-devel at r-project.org <mailto:R-package-devel at r-project.org>
mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel
<https://stat.ethz.ch/mailman/listinfo/r-package-devel>
I kind of prefer Ivan's solution. A variation on Andrew's that doesn't
require you to code the default in two places is:
foo <- function(x, schema = schema(x)) {
if (missing(schema)) {
default <- substitute(schema)
rm(schema)
schema <- eval(default)
}
}
You could also change the name of the argument and let users rely on
partial argument matching:
foo <- function(x, schema. = schema(x)) {
schema <- schema. # if you don't want to type the dot again
if (is.null(schema)) stop("schema missing")
# ...
}
This allows users to say foo(x, schema = myschema(x)) .
However, I'd say it's not a great design. Probably changing your
function name to `getSchema` would be the best overall solution:
foo <- function(x, schema = getSchema(x)) {
if (is.null(schema)) stop("schema missing")
# ...
}
Functions do actions, so their names should be verb-like.
Duncan Murdoch
On 08/08/2022 10:23 a.m., Jan van der Laan wrote:
Hi Andrew and Ivan, Thanks for the suggestion. Both are good suggestions; better than what I have. Andrews solution:
> foo <- function (x, schema = schema(x))
> {
> if (missing(schema)) {
> rm(schema)
> schema <- schema(x)
> }
> }
Ivans:
> function(x, schema = mypackagename::schema(x))
Both would work in this case. Ivans is a bit cleaner/simpler; Andrews appears simpler from a user perspective. Not sure yet which one I will use; I am currently leaning towards Ivans solution. Thanks! Jan On 08-08-2022 15:42, Andrew Simmons wrote:
Hello,
This isn't something that can be fixed in the parser. If an argument
isn't provided, its default value is evaluated inside the function, so
it gives you a loop where schema = schema(x), but then what's schema,
it's schema(x), thus the recursion error. you could do something like this:
foo <- function (x, schema = schema(x))
{
? ? if (missing(schema)) {
? ? ? ? rm(schema)
? ? ? ? schema <- schema(x)
? ? }
}
which, while kinda gross looking, means that schema = schema(x) can be
evaluated without causing a recursion error.
On Mon, Aug 8, 2022, 09:11 Jan van der Laan <rhelp at eoos.dds.nl
<mailto:rhelp at eoos.dds.nl>> wrote:
Not sure if this belongs on r-help or r-package-devel; decided for the
latter as the question is mainly relevant when writing code to be used
by others.
The issue I run into is that I want to write a function similar to:
foo <- function(x, schema = schema(x)) {
? ?if (is.null(schema)) stop("schema missing")
? ?# ...
}
with 'schema()' something like (strongly simplified):
schema <- function(x) attr(x, "schema")
However using both the argument schema and calling the schema()
function
in one of the default arguments is not allowed ans results in the
following somewhat cryptic error message:
Error in foo(1:3) :
? ?promise already under evaluation: recursive default argument
reference or earlier problems?
I am looking for a clean solution to this. I can rename the argument or
function, but calling it something other than schema feels impractical
as both refer to the same thing (the schema of x). The best solution I
have come up with until now is to define a second function to be
used in
default function arguments:
schema_ <- schema
foo <- function(x, schema = schema_(x)) {
? ?if (is.null(schema)) stop("schema missing")
? ?# ...
}
I guess another solution would be:
foo <- function(x, schema) {
? ?if (missing(schema)) schema <- schema(x)
}
But then it is not clear for the user from the interface that the
'schema' argument can be omitted.
I am hoping some of you have other suggestions.
And, is this something that could be 'fixed' in the R-parser?
Thanks,
Jan
______________________________________________
R-package-devel at r-project.org <mailto:R-package-devel at r-project.org>
mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel
<https://stat.ethz.ch/mailman/listinfo/r-package-devel>
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Thanks. I think I prefer Ivan's solution too.
However, I'd say it's not a great design.? Probably changing your
function name to `getSchema` would be the best overall solution:
foo <- function(x, schema = getSchema(x)) {
?? if (is.null(schema)) stop("schema missing")
?? # ...
}
Functions do actions, so their names should be verb-like.
Thought about naming the function something like that. On the other hand, a lot of base R functions follow the following pattern in a similar case foo <- levels(x) levels(x) <- ... (There is also a `schema<-` method). Other examples of this are 'attr', 'class', 'length', 'dim', and 'names'. So for getters and setters the pattern seems to be to not use get and set. I like this feature of R, so would like to stick with it. Best, Jan
Duncan Murdoch On 08/08/2022 10:23 a.m., Jan van der Laan wrote:
Hi Andrew and Ivan,
Thanks for the suggestion. Both are good suggestions; better than what I
have.
Andrews solution:
? > foo <- function (x, schema = schema(x))
? > {
? >????? if (missing(schema)) {
? >????????? rm(schema)
? >????????? schema <- schema(x)
? >????? }
? > }
Ivans:
? > function(x, schema = mypackagename::schema(x))
Both would work in this case. Ivans is a bit cleaner/simpler; Andrews
appears simpler from a user perspective. Not sure yet which one I will
use; I am currently leaning towards Ivans solution.
Thanks!
Jan
On 08-08-2022 15:42, Andrew Simmons wrote:
Hello,
This isn't something that can be fixed in the parser. If an argument
isn't provided, its default value is evaluated inside the function, so
it gives you a loop where schema = schema(x), but then what's schema,
it's schema(x), thus the recursion error. you could do something like
this:
foo <- function (x, schema = schema(x))
{
? ? ? if (missing(schema)) {
? ? ? ? ? rm(schema)
? ? ? ? ? schema <- schema(x)
? ? ? }
}
which, while kinda gross looking, means that schema = schema(x) can be
evaluated without causing a recursion error.
On Mon, Aug 8, 2022, 09:11 Jan van der Laan <rhelp at eoos.dds.nl
<mailto:rhelp at eoos.dds.nl>> wrote:
???? Not sure if this belongs on r-help or r-package-devel; decided
for the
???? latter as the question is mainly relevant when writing code to
be used
???? by others.
???? The issue I run into is that I want to write a function similar to:
???? foo <- function(x, schema = schema(x)) {
????? ? ?if (is.null(schema)) stop("schema missing")
????? ? ?# ...
???? }
???? with 'schema()' something like (strongly simplified):
???? schema <- function(x) attr(x, "schema")
???? However using both the argument schema and calling the schema()
???? function
???? in one of the default arguments is not allowed ans results in the
???? following somewhat cryptic error message:
???? Error in foo(1:3) :
????? ? ?promise already under evaluation: recursive default argument
???? reference or earlier problems?
???? I am looking for a clean solution to this. I can rename the
argument or
???? function, but calling it something other than schema feels
impractical
???? as both refer to the same thing (the schema of x). The best
solution I
???? have come up with until now is to define a second function to be
???? used in
???? default function arguments:
???? schema_ <- schema
???? foo <- function(x, schema = schema_(x)) {
????? ? ?if (is.null(schema)) stop("schema missing")
????? ? ?# ...
???? }
???? I guess another solution would be:
???? foo <- function(x, schema) {
????? ? ?if (missing(schema)) schema <- schema(x)
???? }
???? But then it is not clear for the user from the interface that the
???? 'schema' argument can be omitted.
???? I am hoping some of you have other suggestions.
???? And, is this something that could be 'fixed' in the R-parser?
???? Thanks,
???? Jan
???? ______________________________________________
???? R-package-devel at r-project.org
<mailto:R-package-devel at r-project.org>
???? mailing list
???? https://stat.ethz.ch/mailman/listinfo/r-package-devel
???? <https://stat.ethz.ch/mailman/listinfo/r-package-devel>
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel