Discovered while fixing #238. tfd.tf (and the new_tfd evaluator resolution) accepts evaluator as either a bareword symbol (resolved via match.call/as_name) or a string (resolved via get). A function value passed by reference fails.
library(tf)
x <- tf_rgp(3)
fn <- tf_approx_spline
tfd(x, evaluator = fn) # fails
tfd(x, evaluator = function(x, arg, evaluations) ...) # fails — anonymous
The proper fix lives in tfd.tf (or the new_tfd evaluator resolution path), not in upstream callers. PR #238 originally worked around this by adding a match.call coercion in tf_rebase.tfb.tfd, but that workaround has gaps: it handles a bare symbol but silently fails for tf:::tf_approx_spline (namespace-qualified ::/::: call), anonymous function(x, ...) ..., or any expression. The fix should be at the right layer.
Suggested fix
In R/tfd-class.R's new_tfd (or its evaluator-resolution helper, currently at lines ~24-37), additionally handle the case where the supplied evaluator is already a function:
if (is.function(evaluator)) {
evaluator_fn <- evaluator
evaluator_name <- if (is.null(attr(evaluator, "evaluator_name")))
deparse(substitute(evaluator)) else attr(evaluator, "evaluator_name")
# but substitute() here is in the wrong frame — see the existing deparse/get dance
}
Care needed: substitute()/deparse() won't give a clean name for tf:::tf_approx_spline or anonymous functions. Acceptable behaviors: (a) require a string for the name and accept a function for the value (split into evaluator + evaluator_name), (b) store the function and synthesize a default evaluator_name like "<custom>".
Regression test (add when fixing)
test_that("tfd.tf accepts function-valued evaluator", {
x <- tf_rgp(3)
expect_no_error(y1 <- tfd(x, evaluator = tf_approx_spline))
expect_no_error(y2 <- tfd(x, evaluator = function(x, arg, evaluations) {
# simple linear interp via approx
approx(x = arg, y = evaluations, xout = x, rule = 2)$y
}))
expect_equal(tf_evaluations(y1), tf_evaluations(tfd(x, evaluator = "tf_approx_spline")))
})
Found while reviewing PR for #238. The workaround in tf_rebase.tfb.tfd should be reverted once this is fixed.
Discovered while fixing #238.
tfd.tf(and thenew_tfdevaluator resolution) acceptsevaluatoras either a bareword symbol (resolved viamatch.call/as_name) or a string (resolved viaget). A function value passed by reference fails.The proper fix lives in
tfd.tf(or thenew_tfdevaluator resolution path), not in upstream callers. PR #238 originally worked around this by adding amatch.callcoercion intf_rebase.tfb.tfd, but that workaround has gaps: it handles a bare symbol but silently fails fortf:::tf_approx_spline(namespace-qualified::/:::call), anonymousfunction(x, ...) ..., or any expression. The fix should be at the right layer.Suggested fix
In
R/tfd-class.R'snew_tfd(or its evaluator-resolution helper, currently at lines ~24-37), additionally handle the case where the suppliedevaluatoris already a function:Care needed:
substitute()/deparse()won't give a clean name fortf:::tf_approx_splineor anonymous functions. Acceptable behaviors: (a) require a string for the name and accept a function for the value (split intoevaluator+evaluator_name), (b) store the function and synthesize a defaultevaluator_namelike"<custom>".Regression test (add when fixing)
Found while reviewing PR for #238. The workaround in
tf_rebase.tfb.tfdshould be reverted once this is fixed.