-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
!!!
and call_match()
#1654
Comments
I ended up working around this by first capturing the call w/ capture_args2 <- function(ignore = NULL,
envir = parent.frame(),
fn = sys.function(-1)) {
cl0 <- cl <- sys.call(-1)
# first defuse rlang !!! and := in calls
cl[[1L]] <- quote(rlang::exprs)
cl_exprs <- eval(cl, parent.frame(2L))
# build up a call to base::list() using the exprs
cl <- as.call(c(list, cl_exprs))
# match.call()
cl <- match.call(fn, cl,
expand.dots = !"..." %in% ignore,
envir = parent.frame(2L))
# filter out args to ignore
for(ig in intersect(names(cl), ignore))
cl[[ig]] <- NULL
# eval and capture args
eval(cl, envir = parent.frame(2L))
}
layer_dense <- function(....) {
args <- capture_args()
....
}
|
Worth noting that this workaround produces different implicit injection semantics than we normally have, as implicit injection only works in dots (also called dynamic dots). The implicit injection created by That said we do have a long standing plan of supporting injection in named arguments, e.g. for See how dots evaluation is problematic with a call matching approach: f <- function(...) {
foo <- 1
g(..., foo)
}
g <- function(...) {
bar <- 2
layer_dense(..., bar)
}
local({
qux <- 0
f(qux)
})
#> Error in eval(cl, envir = parent.frame(2L)) : object 'qux' not found We could introduce quosures or quosure-like expressions in the matched call but then you get issues with labelling NSE. |
Thank You @lionel-! Swapping out capture_args2 <- function(ignore = NULL,
envir = parent.frame(),
fn = sys.function(-1)) {
cl0 <- cl <- sys.call(-1)
# first defuse rlang !!! and := in calls
cl[[1L]] <- quote(rlang::quos)
cl_exprs <- eval(cl, parent.frame(2L))
# build up a call to base::list() using the exprs
cl <- as.call(c(list, cl_exprs))
# match.call()
cl <- match.call(fn, cl,
expand.dots = !"..." %in% ignore,
envir = parent.frame(2L))
# filter out args to ignore
for(ig in intersect(names(cl), ignore))
cl[[ig]] <- NULL
# eval and capture args
rlang::eval_tidy(cl, env = parent.frame(2L))
}
initializers <- list(kernel_initializer = "ones",
bias_initializer = "ones")
layer_dense <- function(object, units, activation = NULL, use_bias = TRUE,
kernel_initializer = "glorot_uniform", bias_initializer = "zeros",
kernel_regularizer = NULL, bias_regularizer = NULL,
activity_regularizer = NULL,
kernel_constraint = NULL, bias_constraint = NULL,
..., mask = NULL) {
args2 <- capture_args2()
args2
}
f <- function(...) {
foo <- 1
g(..., foo)
}
g <- function(...) {
bar <- 2
layer_dense(..., bar)
}
local({
qux <- 0
str(f(qux))
str(f(qux, !!!initializers))
})
#> List of 3
#> $ object : num 0
#> $ units : num 1
#> $ activation: num 2
#> List of 5
#> $ object : num 0
#> $ units : num 1
#> $ activation : num 2
#> $ kernel_initializer: chr "ones"
#> $ bias_initializer : chr "ones"
# !!! injection in f
f <- function(...) {
foo <- 1
g(..., foo, !!!initializers)
}
g <- function(...) {
bar <- 2
layer_dense(..., bar)
}
local({
qux <- 0
str(f(qux))
})
#> List of 5
#> $ object : num 0
#> $ units : num 1
#> $ activation : num 2
#> $ kernel_initializer: chr "ones"
#> $ bias_initializer : chr "ones"
# !!! injection in g
f <- function(...) {
foo <- 1
g(..., foo)
}
g <- function(...) {
bar <- 2
layer_dense(..., bar, !!!initializers)
}
local({
qux <- 0
str(f(qux))
})
#> List of 5
#> $ object : num 0
#> $ units : num 1
#> $ activation : num 2
#> $ kernel_initializer: chr "ones"
#> $ bias_initializer : chr "ones" Created on 2023-10-04 with reprex v2.0.2 |
Cool! |
In keras, I naively tried unpacking arguments with
!!!
like this, which resulted in an error:The issue is that
!!!initializer
is matched to the 4th positional argument inlayer_dense()
, rather than being spliced in.layer_dense()
usesmatch.call()
under the hood, and this is whatmatch.call()
returns:rlang::match_call()
returns the same asbase::match.call()
in this situation. It would be nice ifrlang::match_call()
could do better thanmatch.call()
here, splice in the arguments supplied with!!!
, and return instead:The text was updated successfully, but these errors were encountered: